-
Notifications
You must be signed in to change notification settings - Fork 549
Add SharedObjectFromKernel #24401
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
base: main
Are you sure you want to change the base?
Add SharedObjectFromKernel #24401
Conversation
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.
Pull Request Overview
This PR introduces a new API for creating shared tree kernels without relying on subclassing by using makeSharedObjectKind. It refactors the tree factory into a functional factory (treeKernelFactory), updates tests to use an asynchronous load method, and extends SharedTreeKernel to implement the SharedKernel interface and expose a view API.
Reviewed Changes
Copilot reviewed 6 out of 8 changed files in this pull request and generated no comments.
Show a summary per file
File | Description |
---|---|
packages/dds/tree/src/treeFactory.ts | Refactors SharedTree implementation into a factory with makeSharedObjectKind and treeKernelFactory. |
packages/dds/tree/src/test/shared-tree/sharedTree.spec.ts | Updates tests to load shared trees asynchronously and adjusts assertions. |
packages/dds/tree/src/shared-tree/sharedTree.ts | Updates SharedTreeKernel to implement SharedKernel and expose a view API. |
packages/dds/shared-object-base/src/sharedObject.ts | Adds telemetryContextPrefix documentation in the constructor. |
packages/dds/shared-object-base/src/index.ts | Exports new symbols for the shared object kernel. |
Files not reviewed (2)
- packages/dds/shared-object-base/package.json: Language not supported
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (2)
packages/dds/tree/src/treeFactory.ts:65
- [nitpick] The variable name 'k' is ambiguous; consider renaming it to 'kernelInstance' or a similarly descriptive name for clarity.
const k = treeFromKernelArgs(args);
packages/dds/tree/src/test/shared-tree/sharedTree.spec.ts:738
- Ensure that additional test cases are included to verify that the returned object from the asynchronous load method correctly exposes both 'kernel' and 'view', matching the expected API contract.
const tree2 = await sharedTreeFactory.load(
Co-authored-by: Joshua Smithrud <54606601+Josmithr@users.noreply.github.com>
* 1. The runtime, which uses the SharedObject to summarize, load and apply ops. | ||
* 2. The app, who uses the SharedObject to read and write data. | ||
* | ||
* There is some common functionality all shared objects use, provided by {@link SharedObject}. |
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.
Nit: I generally recommend using the link in the first reference to a type (and using ``s for subsequent references).
readonly #kernelArgs: KernelArgs; | ||
|
||
/** | ||
* @param id - String identifier. |
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.
These param docs shouldn't be necessary. Intellisense is smart enough to derive these from the docs on SharedObject
.
See #24495
/** | ||
* Utility to create a IChannelFactory classes. | ||
* @remarks | ||
* Prefer using {@link makeSharedObjectKind} instead of exposing the factory is not needed for legacy API compatibility. |
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.
There is a typo here, but it isn't immediately clear to me what the intended statement was. FYI.
@@ -186,18 +187,32 @@ function getCodecVersions(formatVersion: number): ExplicitCodecVersions { | |||
return versions; | |||
} | |||
|
|||
export type SharedTreeKernelView = Omit<ITreePrivate, keyof (IChannelView & IFluidLoadable)>; |
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.
Docs?
@@ -87,6 +87,12 @@ export interface IFluidDataStoreRuntime | |||
*/ | |||
readonly attachState: AttachState; | |||
|
|||
/** |
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.
Thanks!
} | ||
|
||
/** | ||
* When present on a method, it indicates the methods return value should be replaced with `this` (the wrapper) |
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.
Would be good to add a usage @example
Co-authored-by: Joshua Smithrud <54606601+Josmithr@users.noreply.github.com>
Co-authored-by: Abram Sanderson <Abram.sanderson@gmail.com>
🔗 Found some broken links! 💔 Run a link check locally to find them. See linkcheck output
|
Description
Provide
makeSharedObjectKind
, a new API for implementing ISharedObject which does not rely on subclassing.Note that all the new API and abstractions here are
@internal
and thus could be changed or removed in the future. Additionally the new logic builds SharedObjects using the old APIs so it has no compat implications for the runtime side: this is simply providing a new option for how a SharedObject like SharedTree can be factored.Currently the approach used to define a DDS is to subclass SharedObject.
This makes the logic used to implement the DDS not very composable. If someone wanted to use the logic from two different DDSes to implement a single one (for example to perform a migration, or to reuse the logic in multiple places like Directory almost does with map)) it is difficult.
This approach (Subclassing SharedObject) can also make targeted testing more difficult (for example requiring more mocks), since SharedObject has a significant amount of coupling to runtime types.
Further more, the existing pattern has more boilerplate than necessary as the existing pattern of implementing IChannelFactory for each SharedObject is repetitive.
Additionally, this subclassing based pattern tends to lend itself toward exporting classes, which lead to the use of both SharedObject and the factory classes in exported APIs which still impacts legacy+alpha API surfaces leaking all the base classes into the API surface.
This change introduces a new pattern, where a new purely internal interface is implemented,
SharedKernelFactory
, and passed tomakeSharedObjectKind
which handles everything else. TheSharedKernelFactory
exposes the impelementation of the SharedObject policy as the newSharedKernel
interface. This object is separate from the app facing view, making it easier to expose minimal APIs (Like SharedTree's ITree) without leaking in APIs from SharedObject.While currently this pattern can't support an app facing API with a property which would collide with a property of SharedObject, a limitation of all current SharedObjects, it sets up a approach which could decouple the app facing APi from SharedObject entirely in the future if desired, both making changes to SharedObject and to the app facing API surfaces easier.
In addition to just being a cleaner interface to code SharedObjects against which enable future flexibility, it also is key in enabling the migration approach taken by #23729 as it provides a common abstraction that supported SharedObjects can implement (SharedKernel) that is possible to migrate while preserving the object identity of the SharedObject which wraps it; This scenario is the main motivation for doing this now.
The approach of splitting out the core implementation logic for a DDS was inspired by SharedMap which did this with its SharedMapKernel. This didn't end up getting used to implement SharedDirectory, but the approach seems effective and could have facilatated such use.
This pattern has been successfully applied to tree and is fully hooked up to tree in this change.
This work is split out from #23729 and has some forward looking features to enable supporting SharedMap, like
thisWrap
which is required to implement SharedMap's "set" function which returnsthis
.Reviewer Guidance
The review process is outlined on this wiki page.