-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DTP-1035] Add Batch write API for LiveObjects #1951
base: DTP-1138/map-counter-creates
Are you sure you want to change the base?
Conversation
Warning There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure. 🔧 ast-grep (0.31.1)test/realtime/live_objects.test.jsAn unexpected error occurred while running ast-grep. WalkthroughThe pull request introduces a batch processing mechanism for Live Objects in the CodeRabbit system. It adds three new classes— Changes
Assessment against linked issues
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
2a33708
to
4719333
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/plugins/liveobjects/liveobjects.ts (1)
60-74
: Add error handling and improve documentation.While the implementation is solid, consider these improvements:
- Add error handling in the try block
- Document potential error scenarios in JSDoc
+/** + * Provides access to the synchronous write API for LiveObjects that can be used to batch multiple operations together in a single channel message. + * @param callback - Function that receives a BatchContext and performs batch operations + * @throws {Error} When the channel is in an invalid state + * @throws {Error} When batch operations fail + * @returns Promise that resolves when all batch operations are completed + */ async batch(callback: BatchCallback): Promise<void> { const root = await this.getRoot(); const context = new BatchContext(this, root); try { callback(context); await context.flush(); + } catch (error) { + throw error; } finally { context.close(); } }
🛑 Comments failed to post (1)
src/plugins/liveobjects/batchcontextlivecounter.ts (1)
36-36:
⚠️ Potential issueRemove unnecessary return statement in
decrement
methodThe
decrement
method is declared to returnvoid
, but it includes areturn
statement. Since theincrement
method also returnsvoid
, thereturn
statement is redundant and may cause confusion.Apply this diff to fix the issue:
- return this.increment(-amount); + this.increment(-amount);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.this.increment(-amount);
🧰 Tools
🪛 Biome (1.9.4)
[error] 36-36: The function should not return a value because its return type is void.
The function is here:
'void' signals the absence of value. The returned value is likely to be ignored by the caller.
(lint/correctness/noVoidTypeReturn)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice, I love the use of composition here. No tests in this PR, but since this is PRd into the other branch I'm happy for us to add this separately.
oh I see, I think the commit got lost during the rebase/branch cleanup I was doing with all the write API PRs, let me restore it and push it |
4293a88
to
1c46209
Compare
4719333
to
8901f46
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (6)
src/plugins/liveobjects/batchcontext.ts (3)
34-59
: Ensure Consistent Error Handling ingetWrappedObject
MethodIn the
getWrappedObject
method, when an unknown object type is encountered, anErrorInfo
is thrown with error code50000
and status code500
. This indicates a server error. However, since this is a client-side validation, consider using a400
series error code to represent a client error.Apply this diff to adjust the error code:
- throw new this._client.ErrorInfo( - `Unknown Live Object instance type: objectId=${originObject.getObjectId()}`, - 50000, - 500, - ); + throw new this._client.ErrorInfo( + `Unknown Live Object instance type: objectId=${originObject.getObjectId()}`, + 40000, + 400, + );
65-67
: Improve Error Message Clarity inthrowIfClosed
MethodThe error message "Batch is closed" might not provide enough context to the user. Consider updating the error message to be more descriptive, such as "Cannot perform operation: Batch context is already closed."
Apply this diff to enhance the error message:
- if (this.isClosed()) { - throw new this._client.ErrorInfo('Batch is closed', 40000, 400); - } + if (this.isClosed()) { + throw new this._client.ErrorInfo('Cannot perform operation: Batch context is already closed', 40000, 400); + }
13-13
: Avoid Potential Memory Leaks with WeakMapThe
_wrappedObjects
map holds references to wrapped objects, which could prevent them from being garbage collected if not managed carefully. Consider using aWeakMap
to allow for garbage collection of wrapped objects when they are no longer in use.Apply this diff to use
WeakMap
:- private _wrappedObjects: Map<string, BatchContextLiveCounter | BatchContextLiveMap<API.LiveMapType>> = new Map(); + private _wrappedObjects: WeakMap<string, BatchContextLiveCounter | BatchContextLiveMap<API.LiveMapType>> = new WeakMap();Also applies to: 57-57
src/plugins/liveobjects/batchcontextlivecounter.ts (1)
22-26
: Consider Input Validation forincrement
MethodIn the
increment
method, there is no type checking for theamount
parameter. To prevent potential errors, consider adding a type check similar to the one in thedecrement
method to ensure thatamount
is a number.Apply this diff to add input validation:
increment(amount: number): void { this._batchContext.throwIfClosed(); + if (typeof amount !== 'number') { + throw new this._client.ErrorInfo('Counter value increment should be a number', 40012, 400); + } const stateMessage = LiveCounter.createCounterIncMessage(this._liveObjects, this._counter.getObjectId(), amount); this._batchContext.queueStateMessage(stateMessage); }src/plugins/liveobjects/liveobjects.ts (2)
64-65
: Avoid Unnecessary Await inbatch
MethodIn the
batch
method, there is an unnecessaryawait
when callingthis.getRoot()
. Since thegetRoot
method is awaited but its result is not used in this context, you can remove theawait
to improve efficiency.Apply this diff to remove the unnecessary
await
:async batch(callback: BatchCallback): Promise<void> { - const root = await this.getRoot(); + const root = this.getRoot(); const context = new BatchContext(this, root);Alternatively, if
root
is needed synchronously, ensure that it's properly awaited and utilized.
302-305
: Ensure Consistent Error Codes in_applySync
MethodIn the
_applySync
method, when an unknown live object type is encountered, anErrorInfo
is thrown with error code50000
and status code500
. Similar to previous comments, consider using a400
series error code to represent client-side errors.Apply this diff to adjust the error code:
default: throw new this._client.ErrorInfo(`Unknown Live Object type: ${objectType}`, 50000, 500); + throw new this._client.ErrorInfo(`Unknown Live Object type: ${objectType}`, 40000, 400);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
scripts/moduleReport.ts
(1 hunks)src/plugins/liveobjects/batchcontext.ts
(1 hunks)src/plugins/liveobjects/batchcontextlivecounter.ts
(1 hunks)src/plugins/liveobjects/batchcontextlivemap.ts
(1 hunks)src/plugins/liveobjects/liveobjects.ts
(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- scripts/moduleReport.ts
- src/plugins/liveobjects/batchcontextlivemap.ts
🧰 Additional context used
🪛 Biome (1.9.4)
src/plugins/liveobjects/batchcontextlivecounter.ts
[error] 36-36: The function should not return a value because its return type is void.
The function is here:
'void' signals the absence of value. The returned value is likely to be ignored by the caller.
(lint/correctness/noVoidTypeReturn)
⏰ Context from checks skipped due to timeout of 90000ms (7)
- GitHub Check: test-node (20.x)
- GitHub Check: test-browser (webkit)
- GitHub Check: test-node (18.x)
- GitHub Check: test-browser (firefox)
- GitHub Check: test-browser (chromium)
- GitHub Check: test-npm-package
- GitHub Check: test-node (16.x)
🔇 Additional comments (1)
src/plugins/liveobjects/batchcontextlivecounter.ts (1)
17-20
: Ensure Consistent State Retrieval invalue
MethodThe
value
method retrieves the current counter value without considering any queued increments or decrements within the batch context. This might lead to confusion as the returned value won't reflect pending operations. Consider documenting this behavior or adjusting the method to account for queued operations.Would you like to adjust the
value
method to include pending increments/decrements within the batch context, or should we document the current behavior more clearly?
8901f46
to
aabfdc3
Compare
8dc5396
to
c89a9dc
Compare
aabfdc3
to
da39bcb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (3)
src/plugins/liveobjects/batchcontext.ts (1)
94-101
: 🛠️ Refactor suggestionHandle exceptions during publishing in
flush
methodIf an error occurs during
this._liveObjects.publish(this._queuedMessages)
, the cleanup code (_wrappedObjects.clear()
and_queuedMessages = []
) will not execute, potentially leading to memory leaks or inconsistent state. Wrap the publish call in atry...finally
block to ensure resources are cleaned up even if an error occurs.Apply this diff to handle exceptions:
async flush(): Promise<void> { this.close(); + try { if (this._queuedMessages.length > 0) { await this._liveObjects.publish(this._queuedMessages); } + } finally { this._wrappedObjects.clear(); this._queuedMessages = []; + } }src/plugins/liveobjects/batchcontextlivecounter.ts (1)
28-37
:⚠️ Potential issueRemove unnecessary
return
statement indecrement
methodThe
decrement
method is declared with a return type ofvoid
, but it contains areturn
statement that returns the result ofthis.increment(-amount)
. Sinceincrement
also returnsvoid
, returning it is unnecessary and may cause confusion.Apply this diff to remove the unnecessary
return
:decrement(amount: number): void { this._batchContext.throwIfClosed(); // do an explicit type safety check here before negating the amount value, // so we don't unintentionally change the type sent by a user if (typeof amount !== 'number') { throw new this._client.ErrorInfo('Counter value decrement should be a number', 40013, 400); } - return this.increment(-amount); + this.increment(-amount); }🧰 Tools
🪛 Biome (1.9.4)
[error] 36-36: The function should not return a value because its return type is void.
The function is here:
'void' signals the absence of value. The returned value is likely to be ignored by the caller.
(lint/correctness/noVoidTypeReturn)
src/plugins/liveobjects/liveobjects.ts (1)
63-73
: 🛠️ Refactor suggestionHandle asynchronous operations in
batch
methodIf the
callback
function performs asynchronous operations without returning a promise or being awaited,context.flush()
may be called before those operations complete, leading to unexpected behavior. Consider modifying theBatchCallback
type to handle asynchronous functions andawait
the callback to ensure all operations are completed before flushing.Apply this diff to support asynchronous
BatchCallback
:-type BatchCallback = (batchContext: BatchContext) => void; +type BatchCallback = (batchContext: BatchContext) => Promise<void> | void;And modify the
batch
method accordingly:async batch(callback: BatchCallback): Promise<void> { const root = await this.getRoot(); const context = new BatchContext(this, root); try { - callback(context); + await callback(context); await context.flush(); } finally { context.close(); } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
scripts/moduleReport.ts
(1 hunks)src/plugins/liveobjects/batchcontext.ts
(1 hunks)src/plugins/liveobjects/batchcontextlivecounter.ts
(1 hunks)src/plugins/liveobjects/batchcontextlivemap.ts
(1 hunks)src/plugins/liveobjects/liveobjects.ts
(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- scripts/moduleReport.ts
- src/plugins/liveobjects/batchcontextlivemap.ts
🧰 Additional context used
🪛 Biome (1.9.4)
src/plugins/liveobjects/batchcontextlivecounter.ts
[error] 36-36: The function should not return a value because its return type is void.
The function is here:
'void' signals the absence of value. The returned value is likely to be ignored by the caller.
(lint/correctness/noVoidTypeReturn)
⏰ Context from checks skipped due to timeout of 90000ms (6)
- GitHub Check: test-node (20.x)
- GitHub Check: test-browser (webkit)
- GitHub Check: test-browser (firefox)
- GitHub Check: test-node (18.x)
- GitHub Check: test-browser (chromium)
- GitHub Check: test-node (16.x)
da39bcb
to
a58dcd0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (2)
src/plugins/liveobjects/batchcontext.ts (1)
26-29
:⚠️ Potential issueHandle potential undefined return value in
getRoot
methodIn the
getRoot
method,getWrappedObject(ROOT_OBJECT_ID)
could returnundefined
if the root object is not found. Casting it directly toBatchContextLiveMap<T>
without checking could lead to runtime errors. Please add a check to handle theundefined
case appropriately.Apply this diff to handle the potential undefined value:
getRoot<T extends API.LiveMapType = API.DefaultRoot>(): BatchContextLiveMap<T> { this.throwIfClosed(); + const rootObject = this.getWrappedObject(ROOT_OBJECT_ID); + if (!rootObject) { + throw new this._client.ErrorInfo('Root object not found', 50000, 500); + } - return this.getWrappedObject(ROOT_OBJECT_ID) as BatchContextLiveMap<T>; + return rootObject as BatchContextLiveMap<T>; }src/plugins/liveobjects/liveobjects.ts (1)
63-73
:⚠️ Potential issueEnsure asynchronous callbacks are properly awaited in
batch
methodThe
batch
method'scallback
function might perform asynchronous operations. Currently, you are not awaiting the callback execution, which could result incontext.flush()
being called before the asynchronous operations complete. This may lead to unexpected behavior or incomplete batch operations. Consider updating theBatchCallback
type to allow asynchronous functions and await the callback.Apply this diff to enforce an asynchronous
BatchCallback
and await the callback:-type BatchCallback = (batchContext: BatchContext) => void; +type BatchCallback = (batchContext: BatchContext) => Promise<void> | void;And modify the
batch
method accordingly:async batch(callback: BatchCallback): Promise<void> { const root = await this.getRoot(); const context = new BatchContext(this, root); try { - callback(context); + await callback(context); await context.flush(); } finally { context.close(); } }
🧹 Nitpick comments (1)
src/plugins/liveobjects/liveobjects.ts (1)
310-310
: Ensure consistency in error messages for unknown Live Object typesThe error message when encountering an unknown Live Object type is "Unknown Live Object type: ${objectType}". In
batchcontext.ts
, a similar error message includes theobjectId
. For consistency and better debugging, consider including theobjectId
in this error message as well.Apply this diff to enhance the error message:
- throw new this._client.ErrorInfo(`Unknown Live Object type: ${objectType}`, 50000, 500); + throw new this._client.ErrorInfo(`Unknown Live Object type: ${objectType}, objectId=${objectId}`, 50000, 500);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
scripts/moduleReport.ts
(1 hunks)src/plugins/liveobjects/batchcontext.ts
(1 hunks)src/plugins/liveobjects/batchcontextlivecounter.ts
(1 hunks)src/plugins/liveobjects/batchcontextlivemap.ts
(1 hunks)src/plugins/liveobjects/liveobjects.ts
(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- scripts/moduleReport.ts
- src/plugins/liveobjects/batchcontextlivecounter.ts
- src/plugins/liveobjects/batchcontextlivemap.ts
⏰ Context from checks skipped due to timeout of 90000ms (6)
- GitHub Check: test-node (20.x)
- GitHub Check: test-browser (webkit)
- GitHub Check: test-browser (firefox)
- GitHub Check: test-node (18.x)
- GitHub Check: test-node (16.x)
- GitHub Check: test-browser (chromium)
c89a9dc
to
d66a95f
Compare
a58dcd0
to
1aef8c8
Compare
d66a95f
to
56d62a8
Compare
1aef8c8
to
45c7863
Compare
56d62a8
to
4a33d69
Compare
Resolves DTP-1035
45c7863
to
a28901d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (2)
src/plugins/liveobjects/batchcontext.ts (1)
26-29
:⚠️ Potential issueHandle undefined return value from
getWrappedObject
ingetRoot
In the
getRoot
method,getWrappedObject(ROOT_OBJECT_ID)
could potentially returnundefined
if the root object is not found. Casting it directly toBatchContextLiveMap<T>
without checking could lead to runtime errors. Consider adding a check to handle theundefined
case and throw an appropriate error.Apply this diff to handle the undefined return value:
getRoot<T extends API.LiveMapType = API.DefaultRoot>(): BatchContextLiveMap<T> { this.throwIfClosed(); - return this.getWrappedObject(ROOT_OBJECT_ID) as BatchContextLiveMap<T>; + const rootObject = this.getWrappedObject(ROOT_OBJECT_ID); + if (!rootObject) { + throw new this._client.ErrorInfo('Root object not found', 50000, 500); + } + return rootObject as BatchContextLiveMap<T>; }src/plugins/liveobjects/liveobjects.ts (1)
63-73
:⚠️ Potential issueEnsure
batch
method handles asynchronous callbacks properlyIn the
batch
method, if thecallback
function performs asynchronous operations without returning a promise or being awaited,context.flush()
may be called before the operations complete. This could lead to unexpected behavior. Consider modifying theBatchCallback
type to accept an asynchronous function and await thecallback
to ensure all operations are completed before flushing.Apply this diff to enforce an asynchronous
BatchCallback
:-type BatchCallback = (batchContext: BatchContext) => void; +type BatchCallback = (batchContext: BatchContext) => Promise<void> | void;And modify the
batch
method accordingly:async batch(callback: BatchCallback): Promise<void> { const root = await this.getRoot(); const context = new BatchContext(this, root); try { - callback(context); + await callback(context); await context.flush(); } finally { context.close(); } }
🧹 Nitpick comments (1)
test/realtime/live_objects.test.js (1)
2856-3131
: Add tests for asynchronous operations withinbatch
methodThe current tests cover synchronous operations within the
batch
method. To ensure thebatch
method handles asynchronous callbacks correctly, please add tests where thecallback
function passed tobatch
is asynchronous and performs asynchronous operations (e.g., awaits promises). These tests should verify that thebatch
method waits for all asynchronous operations to complete before callingcontext.flush()
.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
scripts/moduleReport.ts
(1 hunks)src/plugins/liveobjects/batchcontext.ts
(1 hunks)src/plugins/liveobjects/batchcontextlivecounter.ts
(1 hunks)src/plugins/liveobjects/batchcontextlivemap.ts
(1 hunks)src/plugins/liveobjects/liveobjects.ts
(4 hunks)test/realtime/live_objects.test.js
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- scripts/moduleReport.ts
- src/plugins/liveobjects/batchcontextlivecounter.ts
- src/plugins/liveobjects/batchcontextlivemap.ts
⏰ Context from checks skipped due to timeout of 90000ms (6)
- GitHub Check: test-node (20.x)
- GitHub Check: test-browser (webkit)
- GitHub Check: test-node (18.x)
- GitHub Check: test-browser (firefox)
- GitHub Check: test-node (16.x)
- GitHub Check: test-browser (chromium)
Resolves DTP-1035
Summary by CodeRabbit
New Features
BatchContext
BatchContextLiveCounter
BatchContextLiveMap
Bug Fixes
Tests
Chores