Skip to content

Commit

Permalink
materialisation: Add new message attributes and actions handling
Browse files Browse the repository at this point in the history
- Added new message attributes, including `action`, `serial`, `refSerial`, `refType`, `updatedAt`, `deletedAt`, and `operation`.
Additionally, create functions to map message actions between string and number representations.
This update also changes the `fromValues` function to handle action transformations.
  • Loading branch information
splindsay-92 committed Oct 17, 2024
1 parent b3af19a commit deedcea
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 10 deletions.
89 changes: 88 additions & 1 deletion ably.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2335,12 +2335,99 @@ export interface Message {
* Timestamp of when the message was received by Ably, as milliseconds since the Unix epoch.
*/
timestamp?: number;
/**
* The action type of the message, one of the {@link MessageAction} enum values.
*/
action?: MessageAction;
/**
* This message's unique serial.
*/
serial?: string;
/**
* The serial of the message that this message is a reference to.
*/
refSerial?: string;
/**
* The type of reference this message is, in relation to the message it references.
*/
refType?: string;
/**
* If an `update` operation was applied to this message, this will be the timestamp the update occurred.
*/
updatedAt?: number;
/**
* If a `deletion` operation was applied to this message, this will be the timestamp the deletion occurred.
*/
deletedAt?: number;
/**
* If this message resulted from an operation, this will contain the operation details.
*/
operation?: Operation;
}

/**
* Contains the details of an operation, such as update of deletion, supplied by the actioning client.
*/
export interface Operation {
/**
* The client ID of the client that initiated the operation.
*/
clientId?: string;
/**
* The description provided by the client that initiated the operation.
*/
description?: string;
/**
* A JSON object of string key-value pairs that may contain metadata associated with the operation.
*/
metadata?: Record<string, string>;
}

/**
* The namespace containing the different types of message actions.
*/
declare namespace MessageActions {
/**
* Message action has not been set.
*/
type MESSAGE_UNSET = 'message_unset';
/**
* Message action for a newly created message.
*/
type MESSAGE_CREATE = 'message_create';
/**
* Message action for an updated message.
*/
type MESSAGE_UPDATE = 'message_update';
/**
* Message action for a deleted message.
*/
type MESSAGE_DELETE = 'message_delete';
/**
* Message action for a newly created annotation.
*/
type MESSAGE_ANNOTATION_CREATE = 'message_annotation_create';
/**
* Message action for a deleted annotation.
*/
type MESSAGE_ANNOTATION_DELETE = 'message_annotation_delete';
}

/**
* Describes the possible action types used on an {@link Message}.
*/
export type MessageAction =
| MessageActions.MESSAGE_UNSET
| MessageActions.MESSAGE_CREATE
| MessageActions.MESSAGE_UPDATE
| MessageActions.MESSAGE_DELETE
| MessageActions.MESSAGE_ANNOTATION_CREATE
| MessageActions.MESSAGE_ANNOTATION_DELETE;

/**
* A message received from Ably.
*/
export type InboundMessage = Message & Required<Pick<Message, 'id' | 'timestamp'>>;
export type InboundMessage = Message & Required<Pick<Message, 'id' | 'timestamp' | 'serial' | 'action'>>;

/**
* Static utilities related to messages.
Expand Down
11 changes: 6 additions & 5 deletions src/common/lib/types/defaultmessage.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import Message, {
CipherOptions,
fromEncoded,
fromEncodedArray,
encode,
decode,
encode,
EncodingDecodingContext,
fromEncoded,
fromEncodedArray,
fromValues,
} from './message';
import * as API from '../../../../ably';
import Platform from 'common/platform';
Expand All @@ -25,8 +26,8 @@ export class DefaultMessage extends Message {
}

// Used by tests
static fromValues(values: unknown): Message {
return Object.assign(new Message(), values);
static fromValues(values: Message | Record<string, unknown>, stringifyAction?: boolean): Message {
return fromValues(values, stringifyAction);
}

// Used by tests
Expand Down
60 changes: 56 additions & 4 deletions src/common/lib/types/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,32 @@ import * as API from '../../../../ably';
import { IUntypedCryptoStatic } from 'common/types/ICryptoStatic';
import { MsgPack } from 'common/types/msgpack';

const MessageActionArray: API.MessageAction[] = [
'message_unset',
'message_create',
'message_update',
'message_delete',
'message_annotation_create',
'message_annotation_delete',
];

function toMessageActionString(actionNumber: number): API.MessageAction {
if (actionNumber in MessageActionArray) {
return MessageActionArray[actionNumber];
} else {
throw new ErrorInfo(`Unsupported action number: ${actionNumber}`, 40000, 400);
}
}

function toMessageActionNumber(messageAction: API.MessageAction): number {
for (const [index, value] of MessageActionArray.entries()) {
if (value === messageAction) {
return index;
}
}
throw new ErrorInfo(`Unsupported action string: ${messageAction}`, 40000, 400);
}

export type CipherOptions = {
channelCipher: {
encrypt: Function;
Expand Down Expand Up @@ -82,7 +108,7 @@ export async function fromEncoded(
encoded: unknown,
inputOptions?: API.ChannelOptions,
): Promise<Message> {
const msg = fromValues(encoded);
const msg = fromValues(encoded as Message | Record<string, unknown>, true);
const options = normalizeCipherOptions(Crypto, logger, inputOptions ?? null);
/* if decoding fails at any point, catch and return the message decoded to
* the fullest extent possible */
Expand Down Expand Up @@ -260,7 +286,7 @@ export async function fromResponseBody(
}

for (let i = 0; i < body.length; i++) {
const msg = (body[i] = fromValues(body[i]));
const msg = (body[i] = fromValues(body[i], true));
try {
await decode(msg, options);
} catch (e) {
Expand All @@ -270,14 +296,17 @@ export async function fromResponseBody(
return body;
}

export function fromValues(values: unknown): Message {
export function fromValues(values: Message | Record<string, unknown>, stringifyAction?: boolean): Message {
if (stringifyAction) {
values.action = toMessageActionString(values.action as number);
}
return Object.assign(new Message(), values);
}

export function fromValuesArray(values: unknown[]): Message[] {
const count = values.length,
result = new Array(count);
for (let i = 0; i < count; i++) result[i] = fromValues(values[i]);
for (let i = 0; i < count; i++) result[i] = fromValues(values[i] as Record<string, unknown>);
return result;
}

Expand All @@ -304,6 +333,13 @@ class Message {
encoding?: string | null;
extras?: any;
size?: number;
action?: API.MessageAction | number;
serial?: string;
refSerial?: string;
refType?: string;
updatedAt?: number;
deletedAt?: number;
operation?: API.Operation;

/**
* Overload toJSON() to intercept JSON.stringify()
Expand Down Expand Up @@ -334,6 +370,14 @@ class Message {
connectionId: this.connectionId,
connectionKey: this.connectionKey,
extras: this.extras,
serial: this.serial,
// If `action` has not been set, it will be set once received by realtime
action: this.action ? toMessageActionNumber(this.action as API.MessageAction) : 0,
refSerial: this.refSerial,
refType: this.refType,
updatedAt: this.updatedAt,
deletedAt: this.deletedAt,
operation: this.operation,
encoding,
data,
};
Expand All @@ -355,6 +399,14 @@ class Message {
else result += '; data (json)=' + JSON.stringify(this.data);
}
if (this.extras) result += '; extras=' + JSON.stringify(this.extras);

if (this.action) result += '; action=' + this.action;
if (this.serial) result += '; serial=' + this.serial;
if (this.refSerial) result += '; refSerial=' + this.refSerial;
if (this.refType) result += '; refType=' + this.refType;
if (this.updatedAt) result += '; updatedAt=' + this.updatedAt;
if (this.deletedAt) result += '; deletedAt=' + this.deletedAt;
if (this.operation) result += '; operation=' + JSON.stringify(this.operation);
result += ']';
return result;
}
Expand Down

0 comments on commit deedcea

Please sign in to comment.