Skip to content

Commit 7d2e105

Browse files
committed
Refactor encoding/decoding logic in ObjectMessage
Use `WireObjectMessage` to represent the message received from the server which can be decoded into an `ObjectMessage`. `ObjectMessage` can then be encoded into a `WireObjectMessage`.
1 parent bf2aa76 commit 7d2e105

10 files changed

Lines changed: 511 additions & 399 deletions

File tree

src/common/lib/client/realtimechannel.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { normaliseChannelOptions } from '../util/defaults';
1717
import { PaginatedResult } from './paginatedresource';
1818
import type { PushChannel } from 'plugins/push';
1919
import type { WirePresenceMessage } from '../types/presencemessage';
20-
import type { Objects, ObjectMessage } from 'plugins/objects';
20+
import type { Objects, WireObjectMessage } from 'plugins/objects';
2121
import type RealtimePresence from './realtimepresence';
2222
import type RealtimeAnnotations from './realtimeannotations';
2323

@@ -507,7 +507,7 @@ class RealtimeChannel extends EventEmitter {
507507
return this.sendMessage(msg);
508508
}
509509

510-
sendState(objectMessages: ObjectMessage[]): Promise<void> {
510+
sendState(objectMessages: WireObjectMessage[]): Promise<void> {
511511
const msg = protocolMessageFromValues({
512512
action: actions.OBJECT,
513513
channel: this.name,
@@ -623,17 +623,12 @@ class RealtimeChannel extends EventEmitter {
623623
}
624624

625625
populateFieldsFromParent(message);
626-
const objectMessages = message.state;
627626
// need to use the active protocol format instead of just client's useBinaryProtocol option,
628627
// as comet transport does not support msgpack and will default to json without changing useBinaryProtocol.
629628
// message processing is done in the same event loop tick up until this point,
630629
// so we can reliably expect an active protocol to exist and be the one that received the object message.
631630
const format = this.client.connection.connectionManager.getActiveTransportFormat()!;
632-
await Promise.all(
633-
objectMessages.map((om) =>
634-
this.client._objectsPlugin!.ObjectMessage.decode(om, this.client, this.logger, Logger, Utils, format),
635-
),
636-
);
631+
const objectMessages = message.state.map((om) => om.decode(this.client, format));
637632

638633
if (message.action === actions.OBJECT) {
639634
this._objects.handleObjectMessages(objectMessages);

src/common/lib/types/protocolmessage.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ export function fromDeserialized(
6868
);
6969
}
7070

71-
let state: ObjectsPlugin.ObjectMessage[] | undefined;
71+
let state: ObjectsPlugin.WireObjectMessage[] | undefined;
7272
if (objectsPlugin && deserialized.state) {
73-
state = objectsPlugin.ObjectMessage.fromValuesArray(
74-
deserialized.state as ObjectsPlugin.ObjectMessage[],
73+
state = objectsPlugin.WireObjectMessage.fromValuesArray(
74+
deserialized.state as ObjectsPlugin.WireObjectMessage[],
7575
Utils,
7676
MessageEncoding,
7777
);
@@ -128,7 +128,7 @@ export function stringify(
128128
}
129129
if (msg.state && objectsPlugin) {
130130
result +=
131-
'; state=' + toStringArray(objectsPlugin.ObjectMessage.fromValuesArray(msg.state, Utils, MessageEncoding));
131+
'; state=' + toStringArray(objectsPlugin.WireObjectMessage.fromValuesArray(msg.state, Utils, MessageEncoding));
132132
}
133133
if (msg.error) result += '; error=' + ErrorInfo.fromValues(msg.error).toString();
134134
if (msg.auth && msg.auth.accessToken) result += '; token=' + msg.auth.accessToken;
@@ -169,7 +169,7 @@ class ProtocolMessage {
169169
/**
170170
* This will be undefined if we skipped decoding this property due to user not requesting Objects functionality — see {@link fromDeserialized}
171171
*/
172-
state?: ObjectsPlugin.ObjectMessage[]; // TR4r
172+
state?: ObjectsPlugin.WireObjectMessage[]; // TR4r
173173
auth?: unknown;
174174
connectionDetails?: Record<string, unknown>;
175175
params?: Record<string, string>;

src/plugins/objects/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { ObjectMessage } from './objectmessage';
1+
import { ObjectMessage, WireObjectMessage } from './objectmessage';
22
import { Objects } from './objects';
33

4-
export { Objects, ObjectMessage };
4+
export { Objects, ObjectMessage, WireObjectMessage };
55

66
export default {
77
Objects,
88
ObjectMessage,
9+
WireObjectMessage,
910
};

src/plugins/objects/livecounter.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
import { LiveObject, LiveObjectData, LiveObjectUpdate, LiveObjectUpdateNoop } from './liveobject';
22
import { ObjectId } from './objectid';
3-
import { ObjectMessage, ObjectOperation, ObjectOperationAction, ObjectsCounterOp, ObjectState } from './objectmessage';
3+
import {
4+
encodeInitialValue,
5+
ObjectData,
6+
ObjectMessage,
7+
ObjectOperation,
8+
ObjectOperationAction,
9+
ObjectsCounterOp,
10+
ObjectState,
11+
} from './objectmessage';
412
import { Objects } from './objects';
513

614
export interface LiveCounterData extends LiveObjectData {
@@ -29,7 +37,7 @@ export class LiveCounter extends LiveObject<LiveCounterData, LiveCounterUpdate>
2937
*
3038
* @internal
3139
*/
32-
static fromObjectState(objects: Objects, objectState: ObjectState): LiveCounter {
40+
static fromObjectState(objects: Objects, objectState: ObjectState<ObjectData>): LiveCounter {
3341
const obj = new LiveCounter(objects, objectState.objectId);
3442
obj.overrideWithObjectState(objectState);
3543
return obj;
@@ -41,7 +49,7 @@ export class LiveCounter extends LiveObject<LiveCounterData, LiveCounterUpdate>
4149
*
4250
* @internal
4351
*/
44-
static fromObjectOperation(objects: Objects, objectOperation: ObjectOperation): LiveCounter {
52+
static fromObjectOperation(objects: Objects, objectOperation: ObjectOperation<ObjectData>): LiveCounter {
4553
const obj = new LiveCounter(objects, objectOperation.objectId);
4654
obj._mergeInitialDataFromCreateOperation(objectOperation);
4755
return obj;
@@ -63,7 +71,7 @@ export class LiveCounter extends LiveObject<LiveCounterData, LiveCounterUpdate>
6371
action: ObjectOperationAction.COUNTER_INC,
6472
objectId,
6573
counterOp: { amount },
66-
} as ObjectOperation,
74+
} as ObjectOperation<ObjectData>,
6775
},
6876
client.Utils,
6977
client.MessageEncoding,
@@ -83,7 +91,7 @@ export class LiveCounter extends LiveObject<LiveCounterData, LiveCounterUpdate>
8391
}
8492

8593
const initialValueObj = LiveCounter.createInitialValueObject(count);
86-
const { encodedInitialValue, format } = ObjectMessage.encodeInitialValue(initialValueObj, client);
94+
const { encodedInitialValue, format } = encodeInitialValue(initialValueObj, client);
8795
const nonce = client.Utils.cheapRandStr();
8896
const msTimestamp = await client.getTimestamp(true);
8997

@@ -104,7 +112,7 @@ export class LiveCounter extends LiveObject<LiveCounterData, LiveCounterUpdate>
104112
nonce,
105113
initialValue: encodedInitialValue,
106114
initialValueEncoding: format,
107-
} as ObjectOperation,
115+
} as ObjectOperation<ObjectData>,
108116
},
109117
client.Utils,
110118
client.MessageEncoding,
@@ -116,7 +124,7 @@ export class LiveCounter extends LiveObject<LiveCounterData, LiveCounterUpdate>
116124
/**
117125
* @internal
118126
*/
119-
static createInitialValueObject(count?: number): Pick<ObjectOperation, 'counter'> {
127+
static createInitialValueObject(count?: number): Pick<ObjectOperation<ObjectData>, 'counter'> {
120128
return {
121129
counter: {
122130
count: count ?? 0,
@@ -162,7 +170,7 @@ export class LiveCounter extends LiveObject<LiveCounterData, LiveCounterUpdate>
162170
/**
163171
* @internal
164172
*/
165-
applyOperation(op: ObjectOperation, msg: ObjectMessage): void {
173+
applyOperation(op: ObjectOperation<ObjectData>, msg: ObjectMessage): void {
166174
if (op.objectId !== this.getObjectId()) {
167175
throw new this._client.ErrorInfo(
168176
`Cannot apply object operation with objectId=${op.objectId}, to this LiveCounter with objectId=${this.getObjectId()}`,
@@ -226,7 +234,7 @@ export class LiveCounter extends LiveObject<LiveCounterData, LiveCounterUpdate>
226234
* @internal
227235
* @spec RTLC6
228236
*/
229-
overrideWithObjectState(objectState: ObjectState): LiveCounterUpdate | LiveObjectUpdateNoop {
237+
overrideWithObjectState(objectState: ObjectState<ObjectData>): LiveCounterUpdate | LiveObjectUpdateNoop {
230238
if (objectState.objectId !== this.getObjectId()) {
231239
throw new this._client.ErrorInfo(
232240
`Invalid object state: object state objectId=${objectState.objectId}; LiveCounter objectId=${this.getObjectId()}`,
@@ -300,7 +308,7 @@ export class LiveCounter extends LiveObject<LiveCounterData, LiveCounterUpdate>
300308
return { update: { amount: counterDiff } };
301309
}
302310

303-
protected _mergeInitialDataFromCreateOperation(objectOperation: ObjectOperation): LiveCounterUpdate {
311+
protected _mergeInitialDataFromCreateOperation(objectOperation: ObjectOperation<ObjectData>): LiveCounterUpdate {
304312
// if a counter object is missing for the COUNTER_CREATE op, the initial value is implicitly 0 in this case.
305313
// note that it is intentional to SUM the incoming count from the create op.
306314
// if we got here, it means that current counter instance is missing the initial value in its data reference,
@@ -311,15 +319,15 @@ export class LiveCounter extends LiveObject<LiveCounterData, LiveCounterUpdate>
311319
return { update: { amount: objectOperation.counter?.count ?? 0 } };
312320
}
313321

314-
private _throwNoPayloadError(op: ObjectOperation): void {
322+
private _throwNoPayloadError(op: ObjectOperation<ObjectData>): void {
315323
throw new this._client.ErrorInfo(
316324
`No payload found for ${op.action} op for LiveCounter objectId=${this.getObjectId()}`,
317325
92000,
318326
500,
319327
);
320328
}
321329

322-
private _applyCounterCreate(op: ObjectOperation): LiveCounterUpdate | LiveObjectUpdateNoop {
330+
private _applyCounterCreate(op: ObjectOperation<ObjectData>): LiveCounterUpdate | LiveObjectUpdateNoop {
323331
if (this._createOperationIsMerged) {
324332
// There can't be two different create operation for the same object id, because the object id
325333
// fully encodes that operation. This means we can safely ignore any new incoming create operations

0 commit comments

Comments
 (0)