Fluid Framework v2.0.0-internal.6.0.0 (major)
Changes in Fluid Framework v2.0.0-internal.6.0.0
Breaking changes
TestFluidObject.load removed
TestFluidObject.load performed unsafe initialization, and has instead been replaced by direct usage of the constructor plus a call to testFluidObject.initialize(). This should have no impact to your scenario, as instantiation of TestFluidObjects should only be done through TestFluidObjectFactory.
FluidDataStoreRuntime.getChannel throws for channels that do not exist
Previously, calling FluidDataStoreRuntime.getChannel(id)
for a channel that does not exist would wait for the channel to be created (possibly waiting indefinitely if never created). However, there is no safe means to dynamically create a channel in this manner without risking data corruption. The call will instead now throw for non-existent channels.
Removed IContainerContext.existing
The recommended means of checking for existing changed to the instantiateRuntime param in 2021, and the IContainerContext.existing member was formally deprecated in 2.0.0-internal.2.0.0. This member is now removed.
@fluidframework/test-client-utils removed
The @fluidframework/test-client-utils package was deprecated in 2.0.0-internal.5.1.0 and has now been removed.
IChannel.owner removed
The owner property on IChannel was deprecated in 2.0.0-internal.5.1.0 and has now been removed.
IRootSummaryTreeWithStats
removed
IRootSummaryTreeWithStats
was the return type of summarize
method on ContainerRuntime
. It was an internal interface used only in ContainerRuntime
class to to access gcStats
from a call site. gcStats
is not needed in the call site anymore so this interface is removed.
Remove ISegment.parent
This change removed the parent property on the ISegment interface. The property will still exist, but should not generally be used by outside consumers.
There are some circumstances where a consumer may wish to know if a segment is still in the underlying tree and were using the parent property to determine that.
Please change those checks to use the following "parent" in segment && segment.parent !== undefined
Remove unnecessary exports
This change removes a number of interfaces in the merge tree package that are not used in the exported apis surface and therefore should not be used.
combineAppAndProtocolSummary removed from driver-utils
combineAppAndProtocolSummary was deprecated in 2.0.0-internal.3.4.0 and has now been removed.
allSentOpsAckd and processTime events removed from IDeltaManagerEvents
The "allSentOpsAckd" and "processTime" events on the IDeltaManagerEvents interface were deprecated in 2.0.0-internal.2.2.0 and have now been removed.
IConnectionDetailsInternal and IDeltaHandlerStrategy removed
IConnectionDetailsInternal and IDeltaHandlerStrategy from the @fluidframework/container-definitions package were deprecated in 2.0.0-internal.5.2.0 and have now been removed.
Loader.resolve()
throws if LoaderHeader.sequenceNumber
and IContainerLoadMode.opsBeforeReturn
do not match
Calling Loader.resolve()
will now throw an error if LoaderHeader.sequenceNumber
is defined but IContainerLoadMode.opsBeforeReturn
is not set to "sequenceNumber". Vice versa, Loader.resolve()
will also throw an error if IContainerLoadMode.opsBeforeReturn
is set to "sequenceNumber" but LoaderHeader.sequenceNumber
is not defined.
IContainerContext members removed
IContainerContext members disposed, dispose(), serviceConfiguration, and id were deprecated in 2.0.0-internal.5.2.0 and have now been removed.
IDeltaManager members disposed and dispose() removed
IDeltaManager members disposed and dispose() were deprecated in 2.0.0-internal.5.3.0 and have now been removed.
RootDataObject and RootDataObjectProps no longer exported from fluid-static or fluid-framework packages
RootDataObject and RootDataObjectProps are internal implementations and not intended for direct use. Instead use IRootDataObject to refer to the root data object.
EventForwarder and IDisposable members removed from PureDataObject
The EventForwarder and IDisposable members of PureDataObject were deprecated in 2.0.0-internal.5.2.0 and have now been removed.
Client.getSlideToSegment removed
Client.getSlideToSegment was deprecated in 2.0.0-internal.5.3.0 and has been removed. Use getSlideToSegoff function instead.
Remove Interface IFluidResolvedUrl
IFluidResolvedUrl was deprecated and is now removed. All usages should use IResolvedUrl instead
Segments Property Removed from TrackingGroup
Tracking groups can contain more than just segments, so the deprecated segments property has been removed. Use the tracked property instead to see all tracked objects.
contextChanged event on IContainerEvents removed
The contextChanged event on IContainerEvents was deprecated in 2.0.0-internal.2.2.0 and has now been removed.
ICodeAllowList interface removed
The ICodeAllowList interface was deprecated in 2.0.0-internal.3.2.0 and has now been removed.
Remove Deprecated Loggers
This change removes the previously deprecated logger implementations. The following replacements are available:
- replace ChildLogger.create, new TelemetryNullLogger, and new BaseTelemetryNullLogger with createChildLogger
- replace new MultiSinkLogger with createMultiSinkLogger
- replace TelemetryUTLogger with MockLogger
- DebugLogger has no intended replacement
MockLogger is no longer a TelemetryLogger
TelemetryLogger was deprecated and has now been removed, so MockLogger can no longer inherit from it. MockLogger is now a ITelemetryBaseLogger, to get an ITelemetryLogger, or ITelemetryLoggerExt there is a new convenience method, MockLogger.toTelemetryLogger()
EventAndErrorTrackingLogger is no longer a TelemetryLogger
TelemetryLogger was deprecated and has now been removed, so EventAndErrorTrackingLogger can no longer inherit from it. EventAndErrorTrackingLogger is now a ITelemetryBaseLogger, to get an ITelemetryLogger, or ITelemetryLoggerExt call createChildLogger and pass in the EventAndErrorTrackingLogger as the logger property.
Remove packagePathToTelemetryProperty Function
packagePathToTelemetryProperty was previously deprecated and is now removed. Use tagCodeArtifacts instead.
Loader container caching off by default
Loader container caching will now be off by default and the ability to control it is deprecated. Loader caching is deprecated and will be removed in a future release, as well as all caching functionality of containers. Please try not to rely on caching and inform us if you cannot do so.
If you run into trouble with this behavior, please report it ASAP to the FluidFramework team and use the following options (available in this release only) to unblock you:
- set
ILoaderProps.options.cache
totrue
when constructing aLoader
object (see theILoaderOptions
interface) - set
[LoaderHeader.cache]
header totrue
when requesting a container
IntervalConflictResolver removed
IntervalConflictResolver has been removed. Any lingering usages in application code can be removed as well. This change also marks APIs deprecated in #14318 as internal.
Server compatibility change: Upload first summary as base64 blob
We are updating the client to adjust the behavior of the routerlicious driver during the first summary, which will now allow non-UTF-8 compatible binaries to be submitted. (See PR #16286 and PR #16397). To support this change, it is necessary for the servers to run the latest versions that are prepared to work with this new format.
This means that this version of routerlicious-driver requires routerlicious server version >=1.0.0.
When uploading summaries, the SummaryTreeUploadManager and WholeSummaryUploadManager currently use different conversion types based on the content of the ISummaryTree object. If the content is binary, the encoding is base64, and if it comes from a string, the encoding is utf-8. Previously, there was an exception for the first summary, which was always encoded in utf-8. However, recent changes have adjusted the server code to replicate this processing for all summaries. As a result, new clients will need to be run against recent versions of the servers that understand this new format.
Remove closeAndGetPendingLocalState from IContainer
This change removes the deprecated and experimental method closeAndGetPendingLocalState from IContainer. It continues to exist on IContainerExperimental.
IContainerExperimental is an interface that is easily casted to, which enables partners to access experimental features for testing and evaluation. Moving the experimental method off IContainer will reduce exposure and churn on that production interface as we iterate on and finalize our experimental features.
Experimental features should not be used in production environments.
MockContainerRuntime
and MockFluidDataStoreRuntime
have new required methods
MockContainerRuntime
has two new required methods, flush()
and rebase()
. MockFluidDataStoreRuntime
has one new required method, createDeltaConnection
.
To enable testing scenarios involving batches of ops, MockContainerRuntime
has two new required methods, flush()
and rebase()
. Depending on the IMockContainerRuntimeOptions
supplied to the mock runtime, these two new methods must be used accordingly. For the same reason, MockFluidDataStoreRuntime
implements the createDeltaConnection
method, along with managing the mock delta connection lifecycle in a single place.
merge-tree now has new length calculations by default
The merge-tree now enables new length calculations by default and resolves some related performance bugs by making cached segment length nullable.
Hierarchy cached segment length is undefined
if the length of all child nodes is undefined
.
getPendingLocalState and closeAndGetPendingLocalState are now async
getPendingLocalState and closeAndGetPendingLocalState are now async to allow uploading blobs to attach to a DDS (in closing scenario). There is a new parameter in those methods at the container/runtime layer "notifyImminentClosure" which is true only when closing and ensures uploading blobs fast resolve and get attached. Once we apply stashed ops to new container, blob will try to reupload and we will know where to place its references.
Calling ContainerRuntime.closeFn(...)
will no longer call ContainerContext.disposeFn(...)
as well
This means the ContainerRuntime
will no longer be disposed by calling this method.
If you want to dispose the ContainerRuntime
, use the ContainerRuntime.disposeFn
method.
For more information about close vs. dispose expectations, see the Closure section of Loader README.md.
New required method getAliasedDataStoreEntryPoint
in ContainerRuntime
getAliasedDataStoreEntryPoint
API has been added to ContainerRuntime. This can be used to get the entry point to an aliased data stores. To use this API initializeEntryPoint
must be provided when creating FluidDataStoreRuntime
here. getAliasedDataStoreEntryPoint
and initializeEntryPoint
will become required in a future release.
Deprecations and other upcoming changes
Request APIs deprecated from many places
The request
API (associated with the IFluidRouter
interface) has been deprecated on a number of classes and interfaces. The following are impacted:
IRuntime
andContainerRuntime
IFluidDataStoreRuntime
andFluidDataStoreRuntime
IFluidDataStoreChannel
MockFluidDataStoreRuntime
TestFluidObject
Please migrate usage to the corresponding entryPoint
or getEntryPoint()
of the object. The value for these "entryPoint" related APIs is determined from factories (for IRuntime
and IFluidDataStoreRuntime
) via the initializeEntryPoint
method. If no method is passed to the factory, the corresponding entryPoint
and getEntryPoint()
will be undefined.
For an example implementation of initializeEntryPoint
, see pureDataObjectFactory.ts.
More information of the migration off the request pattern, and current status of its removal, is documented in Removing-IFluidRouter.md.
Upgraded typescript transpilation target to ES2020
Upgraded typescript transpilation target to ES2020. This is done in order to decrease the bundle sizes of Fluid Framework packages. This has provided size improvements across the board for ex. Loader, Driver, Runtime etc. Reduced bundle sizes helps to load lesser code in apps and hence also helps to improve the perf.If any app wants to target any older versions of browsers with which this target version is not compatible, then they can use packages like babel to transpile to a older target.
Request APIs deprecated on ILoader
The request
API (associated with the IFluidRouter
interface) has been deprecated on ILoader
and Loader
. Please migrate all usage to using the IContainer.request(...)
method if using a dynamic request URL, or to the IContainer.getEntryPoint()
method if trying to obtain the application-specified root object.
Note: The IContainer.request(...)
method will be deprecated in an upcoming release, so do not rely on this method for a long-term solution (the APIs around entryPoint
and getEntryPoint()
will become required and available for usage in its place).
After calling ILoader.resolve(...)
, call the request(...)
method on the returned IContainer
with a corresponding request URL. For converting a request URL from Loader
to Container
, use the IUrlResolver
passed into the Loader
's constructor. The following is an example of what this change may look like:
// OLD
const request: IRequest;
const urlResolver = new YourUrlResolver();
const loader = new Loader({ urlResolver, ... });
await loader.resolve(request);
const response = loader.request(request);
// NEW
const request: IRequest;
const urlResolver = new YourUrlResolver();
const loader = new Loader({ urlResolver, ... });
const container = await loader.resolve(request);
const resolvedUrl: IRequest = urlResolver.resolve(request);
// Parse the `resolvedUrl.url` property as necessary before passing to `container.request(...)`
// For an example, see the `Loader.resolveCore(...)` method
const parsedResolvedUrl = // implement parse logic here
const response = container.request(parsedResolvedUrl);
Status on removal of the request pattern is tracked in Removing-IFluidRouter.md
getRootDataStore
API is deprecated
The getRootDataStore
API that is used to get aliased data store has been deprecated. It will be removed in a future release. Use getAliasedDataStoreEntryPoint
API to get aliased data stores instead. It returns the data store's entry point which is its IFluidHandle
. To use this API initializeEntryPoint
must be provided when creating FluidDataStoreRuntime
here. getAliasedDataStoreEntryPoint
and initializeEntryPoint
will become required in a future release.
initializeEntryPoint
will become required
The optional initializeEntryPoint
method has been added to a number of constructors. This method argument will become required in an upcoming release and a value will need to be provided to the following classes:
BaseContainerRuntimeFactory
ContainerRuntimeFactoryWithDefaultDataStore
RuntimeFactory
ContainerRuntime
(constructor andloadRuntime
)FluidDataStoreRuntime
For an example implementation of initializeEntryPoint
, see pureDataObjectFactory.ts.
This work will replace the request pattern. See Removing-IFluidRouter.md for more info on this effort.
IContainer's and IDataStore's IFluidRouter capabilities are deprecated.
- The
request
function taking an arbitrary URL and headers is deprecated - However, an overload taking only
{ url: "/" }
is not, for back-compat purposes during the migration from the request pattern to using entryPoint.
About requesting "/" and using entryPoint
Requesting "/" is an idiom some consumers of Fluid Framework have used in their own requestHandler
s (passed to ContainerRuntime.loadRuntime
and FluidDataStoreRuntime
's constructor). The ability to access the "root" or "entry point" of a Container / DataStore will presently be provided by IContainer.getEntryPoint
and IDataStore.entryPoint
. However these are still optional, so a temporary workaround is needed.
See Removing-IFluidRouter.md for more info on this transition from request to entryPoint.
Present Replacement for requesting an arbitrary URL
Suppose you have these variables:
const container: IContainer = ...;
const dataStore: IDataStore = ...;
Before:
container.request({ url, headers });
dataStore.request({ url, headers });
After:
// Assume there is an interface like this in the app's Container implementation
interface CustomUrlRouter {
doRequestRouting(request: { url: string; headers: Record<string, any>; }): any;
}
// Prerequisite: Pass a requestHandler to ContainerRuntime.loadRuntime that routes "/"
// to some root object implementing CustomUrlRouter
const containerRouter: CustomUrlRouter = await container.request({ "/" });
containerRouter.doRequestRouting({ url, headers });
// Prerequisite: Pass a requestHandler to FluidDataStoreRuntime's constructor that routes "/"
// to some root object implementing CustomUrlRouter
const dataStoreRouter: CustomUrlRouter = await dataStore.request({ "/" });
dataStoreRouter.doRequestRouting({ url, headers });
Looking ahead to using entryPoint
In the next major release, getEntryPoint
and entryPoint
should be mandatory and available for use. Then you may replace each call request({ url: "/" })
with a call to get the entryPoint using these functions/properties.