Skip to content

Commit d75a7bd

Browse files
Log instead of throw when publishAndApply cannot apply locally (RTO20c, RTO20d1)
Replace throwing errors with logging when publishAndApply cannot apply operations on ACK. The publish has already succeeded on the server, so throwing would be misleading — operations will be applied via the echo path instead. RTO20c1: log error and return if siteCode unavailable RTO20c2: log error and return if PublishResult.serials has wrong length RTO20d1: log debug and skip individual operations with null serial Up to date with spec c57a8f3. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 02afb90 commit d75a7bd

File tree

1 file changed

+39
-17
lines changed

1 file changed

+39
-17
lines changed

src/plugins/liveobjects/realtimeobject.ts

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -290,36 +290,58 @@ export class RealtimeObject {
290290
`received ACK for ${objectMessages.length} message(s), applying locally; channel=${this._channel.name}`,
291291
);
292292

293-
// RTO20c
293+
// RTO20c - check required information is available
294294
const siteCode = this._channel.connectionManager.connectionDetails?.siteCode;
295+
// RTO20c1
295296
if (!siteCode) {
296-
throw new this._client.ErrorInfo(
297-
'cannot apply operation locally: siteCode not available from connectionDetails',
298-
40000,
299-
400,
297+
this._client.Logger.logAction(
298+
this._client.logger,
299+
this._client.Logger.LOG_ERROR,
300+
'RealtimeObject.publishAndApply()',
301+
`operations will not be applied locally: siteCode not available from connectionDetails; channel=${this._channel.name}`,
300302
);
303+
return;
304+
}
305+
// RTO20c2
306+
if (!publishResult.serials || publishResult.serials.length !== objectMessages.length) {
307+
this._client.Logger.logAction(
308+
this._client.logger,
309+
this._client.Logger.LOG_ERROR,
310+
'RealtimeObject.publishAndApply()',
311+
`operations will not be applied locally: PublishResult.serials has unexpected length (expected ${objectMessages.length}, got ${publishResult.serials?.length}); channel=${this._channel.name}`,
312+
);
313+
return;
301314
}
302315

303316
// RTO20d
304-
const syntheticMessages = objectMessages.map((originalMsg, i) => {
317+
const syntheticMessages: ObjectMessage[] = [];
318+
for (let i = 0; i < objectMessages.length; i++) {
305319
const serial = publishResult.serials[i];
306320

307321
// RTO20d1
308322
if (serial === null) {
309-
throw new this._client.ErrorInfo('cannot apply operation locally: serial is null in PublishResult', 40000, 400);
323+
this._client.Logger.logAction(
324+
this._client.logger,
325+
this._client.Logger.LOG_MICRO,
326+
'RealtimeObject.publishAndApply()',
327+
`operation will not be applied locally: serial is null in PublishResult (index ${i}); channel=${this._channel.name}`,
328+
);
329+
continue;
310330
}
311331

312-
// RTO20d2
313-
return ObjectMessage.fromValues(
314-
{
315-
...originalMsg,
316-
serial, // RTO20d2a
317-
siteCode, // RTO20d2b
318-
},
319-
this._client.Utils,
320-
this._client.MessageEncoding,
332+
// RTO20d2, RTO20d3
333+
syntheticMessages.push(
334+
ObjectMessage.fromValues(
335+
{
336+
...objectMessages[i],
337+
serial, // RTO20d2a
338+
siteCode, // RTO20d2b
339+
},
340+
this._client.Utils,
341+
this._client.MessageEncoding,
342+
),
321343
);
322-
});
344+
}
323345

324346
// RTO20e - Wait for sync to complete if not synced
325347
if (this._state !== ObjectsState.synced) {

0 commit comments

Comments
 (0)