@fluidframework/container-runtime 2.74.0-368706 → 2.74.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/container-runtime.test-files.tar +0 -0
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +20 -2
- package/dist/channelCollection.js.map +1 -1
- package/dist/dataStoreContexts.d.ts +56 -9
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +56 -9
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/runtimeLayerCompatState.d.ts +2 -2
- package/dist/runtimeLayerCompatState.js +1 -1
- package/dist/runtimeLayerCompatState.js.map +1 -1
- package/eslint.config.mts +31 -0
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +20 -2
- package/lib/channelCollection.js.map +1 -1
- package/lib/dataStoreContexts.d.ts +56 -9
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +56 -9
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/runtimeLayerCompatState.d.ts +2 -2
- package/lib/runtimeLayerCompatState.js +1 -1
- package/lib/runtimeLayerCompatState.js.map +1 -1
- package/package.json +21 -20
- package/src/channelCollection.ts +26 -2
- package/src/dataStoreContexts.ts +56 -9
- package/src/packageVersion.ts +1 -1
- package/src/runtimeLayerCompatState.ts +1 -1
|
@@ -5,22 +5,36 @@
|
|
|
5
5
|
import type { IDisposable, ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
6
6
|
import type { FluidDataStoreContext, LocalFluidDataStoreContext } from "./dataStoreContext.js";
|
|
7
7
|
/**
|
|
8
|
+
* Manages the collection of data store contexts, tracking their bound/unbound state.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* A context is "unbound" when it's created locally but not yet made visible (reachable from root).
|
|
12
|
+
* A context is "bound" once it's made locally visible, regardless of the Container's attach state.
|
|
13
|
+
* In attached containers, binding a context immediately sends an attach op and transitions it to Attaching state.
|
|
14
|
+
*
|
|
8
15
|
* @internal
|
|
9
16
|
*/
|
|
10
17
|
export declare class DataStoreContexts implements Iterable<[string, FluidDataStoreContext]>, IDisposable {
|
|
18
|
+
/**
|
|
19
|
+
* Set of IDs for contexts that are unbound (not yet made locally visible).
|
|
20
|
+
* These contexts exist locally but aren't known to other clients (even in an attached container).
|
|
21
|
+
*/
|
|
11
22
|
private readonly notBoundContexts;
|
|
12
23
|
/**
|
|
13
|
-
*
|
|
24
|
+
* Map of all data store contexts (both bound and unbound).
|
|
14
25
|
*/
|
|
15
26
|
private readonly _contexts;
|
|
16
27
|
/**
|
|
17
28
|
* List of pending context waiting either to be bound or to arrive from another client.
|
|
18
29
|
* This covers the case where a local context has been created but not yet bound,
|
|
19
|
-
* or the case where a client knows a store will exist and is waiting on its creation,
|
|
30
|
+
* or the case where a client knows a store will exist (e.g. by alias) and is waiting on its creation,
|
|
20
31
|
* so that a caller may await the deferred's promise until such a time as the context is fully ready.
|
|
21
32
|
* This is a superset of _contexts, since contexts remain here once the Deferred resolves.
|
|
22
33
|
*/
|
|
23
34
|
private readonly deferredContexts;
|
|
35
|
+
/**
|
|
36
|
+
* Lazy disposal logic that disposes all contexts when called.
|
|
37
|
+
*/
|
|
24
38
|
private readonly disposeOnce;
|
|
25
39
|
private readonly _logger;
|
|
26
40
|
constructor(baseLogger: ITelemetryBaseLogger);
|
|
@@ -28,20 +42,46 @@ export declare class DataStoreContexts implements Iterable<[string, FluidDataSto
|
|
|
28
42
|
get size(): number;
|
|
29
43
|
get disposed(): boolean;
|
|
30
44
|
readonly dispose: () => void;
|
|
45
|
+
/**
|
|
46
|
+
* Returns the count of unbound contexts (i.e. local-only on this client)
|
|
47
|
+
*/
|
|
31
48
|
notBoundLength(): number;
|
|
49
|
+
/**
|
|
50
|
+
* Returns true if the given ID corresponds to an unbound context. (i.e. local-only on this client)
|
|
51
|
+
*/
|
|
32
52
|
isNotBound(id: string): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Returns true if a context with the given ID exists (bound or unbound).
|
|
55
|
+
*/
|
|
33
56
|
has(id: string): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Returns the context with the given ID, or undefined if not found.
|
|
59
|
+
* This returns both bound and unbound contexts.
|
|
60
|
+
*/
|
|
34
61
|
get(id: string): FluidDataStoreContext | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* Deletes the context with the given ID from all internal maps.
|
|
64
|
+
* @returns True if the context was found and deleted, false otherwise.
|
|
65
|
+
*/
|
|
35
66
|
delete(id: string): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Map of recently deleted contexts for diagnostic purposes for GC.
|
|
69
|
+
* Allows retrieval of context information even after deletion for logging/telemetry.
|
|
70
|
+
*/
|
|
36
71
|
private readonly _recentlyDeletedContexts;
|
|
72
|
+
/**
|
|
73
|
+
* Returns a recently deleted context by ID, or undefined if not found.
|
|
74
|
+
* Used for diagnostic logging for GC, when a deleted context is referenced.
|
|
75
|
+
*/
|
|
37
76
|
getRecentlyDeletedContext(id: string): FluidDataStoreContext | undefined;
|
|
38
77
|
/**
|
|
39
|
-
*
|
|
40
|
-
* or undefined if
|
|
78
|
+
* Returns the unbound local context with the given ID.
|
|
79
|
+
* @returns The unbound context, or undefined if not found or not unbound.
|
|
41
80
|
*/
|
|
42
81
|
getUnbound(id: string): LocalFluidDataStoreContext | undefined;
|
|
43
82
|
/**
|
|
44
|
-
*
|
|
83
|
+
* Adds the given context to the collection, marking it as unbound (not yet locally visible).
|
|
84
|
+
* Asserts that no context with this ID already exists.
|
|
45
85
|
*/
|
|
46
86
|
addUnbound(context: LocalFluidDataStoreContext): void;
|
|
47
87
|
/**
|
|
@@ -51,9 +91,14 @@ export declare class DataStoreContexts implements Iterable<[string, FluidDataSto
|
|
|
51
91
|
* @param wait - If false, return undefined if the context isn't present and ready now. Otherwise, wait for it.
|
|
52
92
|
*/
|
|
53
93
|
getBoundOrRemoted(id: string, wait: boolean): Promise<FluidDataStoreContext | undefined>;
|
|
94
|
+
/**
|
|
95
|
+
* Gets or creates a deferred promise for the given context ID.
|
|
96
|
+
* Used to allow waiting for contexts that don't exist yet.
|
|
97
|
+
*/
|
|
54
98
|
private ensureDeferred;
|
|
55
99
|
/**
|
|
56
|
-
*
|
|
100
|
+
* Marks the context with the given ID as bound (locally visible).
|
|
101
|
+
* Removes it from the unbound set and resolves its deferred promise.
|
|
57
102
|
*/
|
|
58
103
|
bind(id: string): void;
|
|
59
104
|
/**
|
|
@@ -62,9 +107,11 @@ export declare class DataStoreContexts implements Iterable<[string, FluidDataSto
|
|
|
62
107
|
*/
|
|
63
108
|
private resolveDeferred;
|
|
64
109
|
/**
|
|
65
|
-
*
|
|
66
|
-
* This
|
|
67
|
-
*
|
|
110
|
+
* Adds the given context to the collection as already bound or from a remote client.
|
|
111
|
+
* This is used when:
|
|
112
|
+
* - Adding a local context that's already been bound via the bind() method, OR
|
|
113
|
+
* - Adding a remote context that was created by another client.
|
|
114
|
+
* The context's deferred promise is resolved immediately.
|
|
68
115
|
*/
|
|
69
116
|
addBoundOrRemoted(context: FluidDataStoreContext): void;
|
|
70
117
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataStoreContexts.d.ts","sourceRoot":"","sources":["../src/dataStoreContexts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAOzF,OAAO,KAAK,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAE/F
|
|
1
|
+
{"version":3,"file":"dataStoreContexts.d.ts","sourceRoot":"","sources":["../src/dataStoreContexts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAOzF,OAAO,KAAK,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAE/F;;;;;;;;;GASG;AACH,qBAAa,iBACZ,YAAW,QAAQ,CAAC,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC,EAAE,WAAW;IAEjE;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;IAEtD;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IAEtE;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsD;IAEvF;;OAEG;IAEH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAiBzB;IAEH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;gBAElC,UAAU,EAAE,oBAAoB;IAI5C,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAI9D,IAAW,IAAI,IAAI,MAAM,CAExB;IAED,IAAW,QAAQ,IAAI,OAAO,CAE7B;IACD,SAAgB,OAAO,QAAO,IAAI,CAA2B;IAE7D;;OAEG;IACI,cAAc,IAAI,MAAM;IAI/B;;OAEG;IACI,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAItC;;OAEG;IACI,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI/B;;;OAGG;IACI,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS;IAIzD;;;OAGG;IACI,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAWlC;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAC9B;IAEX;;;OAGG;IACI,yBAAyB,CAAC,EAAE,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS;IAI/E;;;OAGG;IACI,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,0BAA0B,GAAG,SAAS;IASrE;;;OAGG;IACI,UAAU,CAAC,OAAO,EAAE,0BAA0B,GAAG,IAAI;IAU5D;;;;;OAKG;IACU,iBAAiB,CAC7B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC;IAU7C;;;OAGG;IACH,OAAO,CAAC,cAAc;IAWtB;;;OAGG;IACI,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAO7B;;;OAGG;IACH,OAAO,CAAC,eAAe;IAavB;;;;;;OAMG;IACI,iBAAiB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI;CAU9D"}
|
package/lib/dataStoreContexts.js
CHANGED
|
@@ -5,23 +5,37 @@
|
|
|
5
5
|
import { assert, Deferred, Lazy } from "@fluidframework/core-utils/internal";
|
|
6
6
|
import { createChildLogger, } from "@fluidframework/telemetry-utils/internal";
|
|
7
7
|
/**
|
|
8
|
+
* Manages the collection of data store contexts, tracking their bound/unbound state.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* A context is "unbound" when it's created locally but not yet made visible (reachable from root).
|
|
12
|
+
* A context is "bound" once it's made locally visible, regardless of the Container's attach state.
|
|
13
|
+
* In attached containers, binding a context immediately sends an attach op and transitions it to Attaching state.
|
|
14
|
+
*
|
|
8
15
|
* @internal
|
|
9
16
|
*/
|
|
10
17
|
export class DataStoreContexts {
|
|
11
18
|
constructor(baseLogger) {
|
|
19
|
+
/**
|
|
20
|
+
* Set of IDs for contexts that are unbound (not yet made locally visible).
|
|
21
|
+
* These contexts exist locally but aren't known to other clients (even in an attached container).
|
|
22
|
+
*/
|
|
12
23
|
this.notBoundContexts = new Set();
|
|
13
24
|
/**
|
|
14
|
-
*
|
|
25
|
+
* Map of all data store contexts (both bound and unbound).
|
|
15
26
|
*/
|
|
16
27
|
this._contexts = new Map();
|
|
17
28
|
/**
|
|
18
29
|
* List of pending context waiting either to be bound or to arrive from another client.
|
|
19
30
|
* This covers the case where a local context has been created but not yet bound,
|
|
20
|
-
* or the case where a client knows a store will exist and is waiting on its creation,
|
|
31
|
+
* or the case where a client knows a store will exist (e.g. by alias) and is waiting on its creation,
|
|
21
32
|
* so that a caller may await the deferred's promise until such a time as the context is fully ready.
|
|
22
33
|
* This is a superset of _contexts, since contexts remain here once the Deferred resolves.
|
|
23
34
|
*/
|
|
24
35
|
this.deferredContexts = new Map();
|
|
36
|
+
/**
|
|
37
|
+
* Lazy disposal logic that disposes all contexts when called.
|
|
38
|
+
*/
|
|
25
39
|
// eslint-disable-next-line unicorn/consistent-function-scoping -- Property is defined once; no need to extract inner lambda
|
|
26
40
|
this.disposeOnce = new Lazy(() => {
|
|
27
41
|
// close/stop all store contexts
|
|
@@ -39,6 +53,10 @@ export class DataStoreContexts {
|
|
|
39
53
|
}
|
|
40
54
|
});
|
|
41
55
|
this.dispose = () => this.disposeOnce.value;
|
|
56
|
+
/**
|
|
57
|
+
* Map of recently deleted contexts for diagnostic purposes for GC.
|
|
58
|
+
* Allows retrieval of context information even after deletion for logging/telemetry.
|
|
59
|
+
*/
|
|
42
60
|
this._recentlyDeletedContexts = new Map();
|
|
43
61
|
this._logger = createChildLogger({ logger: baseLogger });
|
|
44
62
|
}
|
|
@@ -51,18 +69,35 @@ export class DataStoreContexts {
|
|
|
51
69
|
get disposed() {
|
|
52
70
|
return this.disposeOnce.evaluated;
|
|
53
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Returns the count of unbound contexts (i.e. local-only on this client)
|
|
74
|
+
*/
|
|
54
75
|
notBoundLength() {
|
|
55
76
|
return this.notBoundContexts.size;
|
|
56
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Returns true if the given ID corresponds to an unbound context. (i.e. local-only on this client)
|
|
80
|
+
*/
|
|
57
81
|
isNotBound(id) {
|
|
58
82
|
return this.notBoundContexts.has(id);
|
|
59
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Returns true if a context with the given ID exists (bound or unbound).
|
|
86
|
+
*/
|
|
60
87
|
has(id) {
|
|
61
88
|
return this._contexts.has(id);
|
|
62
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Returns the context with the given ID, or undefined if not found.
|
|
92
|
+
* This returns both bound and unbound contexts.
|
|
93
|
+
*/
|
|
63
94
|
get(id) {
|
|
64
95
|
return this._contexts.get(id);
|
|
65
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Deletes the context with the given ID from all internal maps.
|
|
99
|
+
* @returns True if the context was found and deleted, false otherwise.
|
|
100
|
+
*/
|
|
66
101
|
delete(id) {
|
|
67
102
|
this.deferredContexts.delete(id);
|
|
68
103
|
this.notBoundContexts.delete(id);
|
|
@@ -71,12 +106,16 @@ export class DataStoreContexts {
|
|
|
71
106
|
this._recentlyDeletedContexts.set(id, context);
|
|
72
107
|
return this._contexts.delete(id);
|
|
73
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Returns a recently deleted context by ID, or undefined if not found.
|
|
111
|
+
* Used for diagnostic logging for GC, when a deleted context is referenced.
|
|
112
|
+
*/
|
|
74
113
|
getRecentlyDeletedContext(id) {
|
|
75
114
|
return this._recentlyDeletedContexts.get(id);
|
|
76
115
|
}
|
|
77
116
|
/**
|
|
78
|
-
*
|
|
79
|
-
* or undefined if
|
|
117
|
+
* Returns the unbound local context with the given ID.
|
|
118
|
+
* @returns The unbound context, or undefined if not found or not unbound.
|
|
80
119
|
*/
|
|
81
120
|
getUnbound(id) {
|
|
82
121
|
const context = this._contexts.get(id);
|
|
@@ -86,7 +125,8 @@ export class DataStoreContexts {
|
|
|
86
125
|
return context;
|
|
87
126
|
}
|
|
88
127
|
/**
|
|
89
|
-
*
|
|
128
|
+
* Adds the given context to the collection, marking it as unbound (not yet locally visible).
|
|
129
|
+
* Asserts that no context with this ID already exists.
|
|
90
130
|
*/
|
|
91
131
|
addUnbound(context) {
|
|
92
132
|
const id = context.id;
|
|
@@ -108,6 +148,10 @@ export class DataStoreContexts {
|
|
|
108
148
|
}
|
|
109
149
|
return deferredContext.promise;
|
|
110
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Gets or creates a deferred promise for the given context ID.
|
|
153
|
+
* Used to allow waiting for contexts that don't exist yet.
|
|
154
|
+
*/
|
|
111
155
|
ensureDeferred(id) {
|
|
112
156
|
const deferred = this.deferredContexts.get(id);
|
|
113
157
|
if (deferred) {
|
|
@@ -118,7 +162,8 @@ export class DataStoreContexts {
|
|
|
118
162
|
return newDeferred;
|
|
119
163
|
}
|
|
120
164
|
/**
|
|
121
|
-
*
|
|
165
|
+
* Marks the context with the given ID as bound (locally visible).
|
|
166
|
+
* Removes it from the unbound set and resolves its deferred promise.
|
|
122
167
|
*/
|
|
123
168
|
bind(id) {
|
|
124
169
|
const removed = this.notBoundContexts.delete(id);
|
|
@@ -138,9 +183,11 @@ export class DataStoreContexts {
|
|
|
138
183
|
deferred.resolve(context);
|
|
139
184
|
}
|
|
140
185
|
/**
|
|
141
|
-
*
|
|
142
|
-
* This
|
|
143
|
-
*
|
|
186
|
+
* Adds the given context to the collection as already bound or from a remote client.
|
|
187
|
+
* This is used when:
|
|
188
|
+
* - Adding a local context that's already been bound via the bind() method, OR
|
|
189
|
+
* - Adding a remote context that was created by another client.
|
|
190
|
+
* The context's deferred promise is resolved immediately.
|
|
144
191
|
*/
|
|
145
192
|
addBoundOrRemoted(context) {
|
|
146
193
|
const id = context.id;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataStoreContexts.js","sourceRoot":"","sources":["../src/dataStoreContexts.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IDisposable, ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert, Deferred, Lazy } from \"@fluidframework/core-utils/internal\";\nimport {\n\ttype ITelemetryLoggerExt,\n\tcreateChildLogger,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { FluidDataStoreContext, LocalFluidDataStoreContext } from \"./dataStoreContext.js\";\n\n/**\n * @internal\n */\nexport class DataStoreContexts\n\timplements Iterable<[string, FluidDataStoreContext]>, IDisposable\n{\n\tprivate readonly notBoundContexts = new Set<string>();\n\n\t/**\n\t * Attached and loaded context proxies\n\t */\n\tprivate readonly _contexts = new Map<string, FluidDataStoreContext>();\n\n\t/**\n\t * List of pending context waiting either to be bound or to arrive from another client.\n\t * This covers the case where a local context has been created but not yet bound,\n\t * or the case where a client knows a store will exist and is waiting on its creation,\n\t * so that a caller may await the deferred's promise until such a time as the context is fully ready.\n\t * This is a superset of _contexts, since contexts remain here once the Deferred resolves.\n\t */\n\tprivate readonly deferredContexts = new Map<string, Deferred<FluidDataStoreContext>>();\n\n\t// eslint-disable-next-line unicorn/consistent-function-scoping -- Property is defined once; no need to extract inner lambda\n\tprivate readonly disposeOnce = new Lazy<void>(() => {\n\t\t// close/stop all store contexts\n\t\tfor (const [fluidDataStoreId, contextD] of this.deferredContexts) {\n\t\t\tcontextD.promise\n\t\t\t\t.then((context) => {\n\t\t\t\t\tcontext.dispose();\n\t\t\t\t})\n\t\t\t\t.catch((contextError) => {\n\t\t\t\t\tthis._logger.sendErrorEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"FluidDataStoreContextDisposeError\",\n\t\t\t\t\t\t\tfluidDataStoreId,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcontextError,\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t}\n\t});\n\n\tprivate readonly _logger: ITelemetryLoggerExt;\n\n\tconstructor(baseLogger: ITelemetryBaseLogger) {\n\t\tthis._logger = createChildLogger({ logger: baseLogger });\n\t}\n\n\t[Symbol.iterator](): Iterator<[string, FluidDataStoreContext]> {\n\t\treturn this._contexts.entries();\n\t}\n\n\tpublic get size(): number {\n\t\treturn this._contexts.size;\n\t}\n\n\tpublic get disposed(): boolean {\n\t\treturn this.disposeOnce.evaluated;\n\t}\n\tpublic readonly dispose = (): void => this.disposeOnce.value;\n\n\tpublic notBoundLength(): number {\n\t\treturn this.notBoundContexts.size;\n\t}\n\n\tpublic isNotBound(id: string): boolean {\n\t\treturn this.notBoundContexts.has(id);\n\t}\n\n\tpublic has(id: string): boolean {\n\t\treturn this._contexts.has(id);\n\t}\n\n\tpublic get(id: string): FluidDataStoreContext | undefined {\n\t\treturn this._contexts.get(id);\n\t}\n\n\tpublic delete(id: string): boolean {\n\t\tthis.deferredContexts.delete(id);\n\t\tthis.notBoundContexts.delete(id);\n\n\t\t// Stash the context here in case it's requested in this session, we can log some details about it\n\t\tconst context = this._contexts.get(id);\n\t\tthis._recentlyDeletedContexts.set(id, context);\n\n\t\treturn this._contexts.delete(id);\n\t}\n\n\tprivate readonly _recentlyDeletedContexts: Map<string, FluidDataStoreContext | undefined> =\n\t\tnew Map();\n\n\tpublic getRecentlyDeletedContext(id: string): FluidDataStoreContext | undefined {\n\t\treturn this._recentlyDeletedContexts.get(id);\n\t}\n\n\t/**\n\t * Return the unbound local context with the given id,\n\t * or undefined if it's not found or not unbound.\n\t */\n\tpublic getUnbound(id: string): LocalFluidDataStoreContext | undefined {\n\t\tconst context = this._contexts.get(id);\n\t\tif (context === undefined || !this.notBoundContexts.has(id)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn context as LocalFluidDataStoreContext;\n\t}\n\n\t/**\n\t * Add the given context, marking it as to-be-bound\n\t */\n\tpublic addUnbound(context: LocalFluidDataStoreContext): void {\n\t\tconst id = context.id;\n\t\tassert(!this._contexts.has(id), 0x158 /* \"Creating store with existing ID\" */);\n\n\t\tthis._contexts.set(id, context);\n\n\t\tthis.notBoundContexts.add(id);\n\t\tthis.ensureDeferred(id);\n\t}\n\n\t/**\n\t * Get the context with the given id, once it exists locally and is attached.\n\t * e.g. If created locally, it must be bound, or if created remotely then it's fine as soon as it's sync'd in.\n\t * @param id - The id of the context to get\n\t * @param wait - If false, return undefined if the context isn't present and ready now. Otherwise, wait for it.\n\t */\n\tpublic async getBoundOrRemoted(\n\t\tid: string,\n\t\twait: boolean,\n\t): Promise<FluidDataStoreContext | undefined> {\n\t\tconst deferredContext = this.ensureDeferred(id);\n\n\t\tif (!wait && !deferredContext.isCompleted) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn deferredContext.promise;\n\t}\n\n\tprivate ensureDeferred(id: string): Deferred<FluidDataStoreContext> {\n\t\tconst deferred = this.deferredContexts.get(id);\n\t\tif (deferred) {\n\t\t\treturn deferred;\n\t\t}\n\n\t\tconst newDeferred = new Deferred<FluidDataStoreContext>();\n\t\tthis.deferredContexts.set(id, newDeferred);\n\t\treturn newDeferred;\n\t}\n\n\t/**\n\t * Update this context as bound\n\t */\n\tpublic bind(id: string): void {\n\t\tconst removed: boolean = this.notBoundContexts.delete(id);\n\t\tassert(removed, 0x159 /* \"The given id was not found in notBoundContexts to delete\" */);\n\n\t\tthis.resolveDeferred(id);\n\t}\n\n\t/**\n\t * Triggers the deferred to resolve, indicating the context is not local-only\n\t * @param id - The id of the context to resolve to\n\t */\n\tprivate resolveDeferred(id: string): void {\n\t\tconst context = this._contexts.get(id);\n\t\tassert(!!context, 0x15a /* \"Cannot find context to resolve to\" */);\n\t\tassert(\n\t\t\t!this.notBoundContexts.has(id),\n\t\t\t0x15b /* \"Expected this id to already be removed from notBoundContexts\" */,\n\t\t);\n\n\t\tconst deferred = this.deferredContexts.get(id);\n\t\tassert(!!deferred, 0x15c /* \"Cannot find deferred to resolve\" */);\n\t\tdeferred.resolve(context);\n\t}\n\n\t/**\n\t * Add the given context, marking it as not local-only.\n\t * This could be because it's a local context that's been bound, or because it's a remote context.\n\t * @param context - The context to add\n\t */\n\tpublic addBoundOrRemoted(context: FluidDataStoreContext): void {\n\t\tconst id = context.id;\n\t\tassert(!this._contexts.has(id), 0x15d /* \"Creating store with existing ID\" */);\n\n\t\tthis._contexts.set(id, context);\n\n\t\t// Resolve the deferred immediately since this context is not unbound\n\t\tthis.ensureDeferred(id);\n\t\tthis.resolveDeferred(id);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dataStoreContexts.js","sourceRoot":"","sources":["../src/dataStoreContexts.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IDisposable, ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert, Deferred, Lazy } from \"@fluidframework/core-utils/internal\";\nimport {\n\ttype ITelemetryLoggerExt,\n\tcreateChildLogger,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { FluidDataStoreContext, LocalFluidDataStoreContext } from \"./dataStoreContext.js\";\n\n/**\n * Manages the collection of data store contexts, tracking their bound/unbound state.\n *\n * @remarks\n * A context is \"unbound\" when it's created locally but not yet made visible (reachable from root).\n * A context is \"bound\" once it's made locally visible, regardless of the Container's attach state.\n * In attached containers, binding a context immediately sends an attach op and transitions it to Attaching state.\n *\n * @internal\n */\nexport class DataStoreContexts\n\timplements Iterable<[string, FluidDataStoreContext]>, IDisposable\n{\n\t/**\n\t * Set of IDs for contexts that are unbound (not yet made locally visible).\n\t * These contexts exist locally but aren't known to other clients (even in an attached container).\n\t */\n\tprivate readonly notBoundContexts = new Set<string>();\n\n\t/**\n\t * Map of all data store contexts (both bound and unbound).\n\t */\n\tprivate readonly _contexts = new Map<string, FluidDataStoreContext>();\n\n\t/**\n\t * List of pending context waiting either to be bound or to arrive from another client.\n\t * This covers the case where a local context has been created but not yet bound,\n\t * or the case where a client knows a store will exist (e.g. by alias) and is waiting on its creation,\n\t * so that a caller may await the deferred's promise until such a time as the context is fully ready.\n\t * This is a superset of _contexts, since contexts remain here once the Deferred resolves.\n\t */\n\tprivate readonly deferredContexts = new Map<string, Deferred<FluidDataStoreContext>>();\n\n\t/**\n\t * Lazy disposal logic that disposes all contexts when called.\n\t */\n\t// eslint-disable-next-line unicorn/consistent-function-scoping -- Property is defined once; no need to extract inner lambda\n\tprivate readonly disposeOnce = new Lazy<void>(() => {\n\t\t// close/stop all store contexts\n\t\tfor (const [fluidDataStoreId, contextD] of this.deferredContexts) {\n\t\t\tcontextD.promise\n\t\t\t\t.then((context) => {\n\t\t\t\t\tcontext.dispose();\n\t\t\t\t})\n\t\t\t\t.catch((contextError) => {\n\t\t\t\t\tthis._logger.sendErrorEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"FluidDataStoreContextDisposeError\",\n\t\t\t\t\t\t\tfluidDataStoreId,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcontextError,\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t}\n\t});\n\n\tprivate readonly _logger: ITelemetryLoggerExt;\n\n\tconstructor(baseLogger: ITelemetryBaseLogger) {\n\t\tthis._logger = createChildLogger({ logger: baseLogger });\n\t}\n\n\t[Symbol.iterator](): Iterator<[string, FluidDataStoreContext]> {\n\t\treturn this._contexts.entries();\n\t}\n\n\tpublic get size(): number {\n\t\treturn this._contexts.size;\n\t}\n\n\tpublic get disposed(): boolean {\n\t\treturn this.disposeOnce.evaluated;\n\t}\n\tpublic readonly dispose = (): void => this.disposeOnce.value;\n\n\t/**\n\t * Returns the count of unbound contexts (i.e. local-only on this client)\n\t */\n\tpublic notBoundLength(): number {\n\t\treturn this.notBoundContexts.size;\n\t}\n\n\t/**\n\t * Returns true if the given ID corresponds to an unbound context. (i.e. local-only on this client)\n\t */\n\tpublic isNotBound(id: string): boolean {\n\t\treturn this.notBoundContexts.has(id);\n\t}\n\n\t/**\n\t * Returns true if a context with the given ID exists (bound or unbound).\n\t */\n\tpublic has(id: string): boolean {\n\t\treturn this._contexts.has(id);\n\t}\n\n\t/**\n\t * Returns the context with the given ID, or undefined if not found.\n\t * This returns both bound and unbound contexts.\n\t */\n\tpublic get(id: string): FluidDataStoreContext | undefined {\n\t\treturn this._contexts.get(id);\n\t}\n\n\t/**\n\t * Deletes the context with the given ID from all internal maps.\n\t * @returns True if the context was found and deleted, false otherwise.\n\t */\n\tpublic delete(id: string): boolean {\n\t\tthis.deferredContexts.delete(id);\n\t\tthis.notBoundContexts.delete(id);\n\n\t\t// Stash the context here in case it's requested in this session, we can log some details about it\n\t\tconst context = this._contexts.get(id);\n\t\tthis._recentlyDeletedContexts.set(id, context);\n\n\t\treturn this._contexts.delete(id);\n\t}\n\n\t/**\n\t * Map of recently deleted contexts for diagnostic purposes for GC.\n\t * Allows retrieval of context information even after deletion for logging/telemetry.\n\t */\n\tprivate readonly _recentlyDeletedContexts: Map<string, FluidDataStoreContext | undefined> =\n\t\tnew Map();\n\n\t/**\n\t * Returns a recently deleted context by ID, or undefined if not found.\n\t * Used for diagnostic logging for GC, when a deleted context is referenced.\n\t */\n\tpublic getRecentlyDeletedContext(id: string): FluidDataStoreContext | undefined {\n\t\treturn this._recentlyDeletedContexts.get(id);\n\t}\n\n\t/**\n\t * Returns the unbound local context with the given ID.\n\t * @returns The unbound context, or undefined if not found or not unbound.\n\t */\n\tpublic getUnbound(id: string): LocalFluidDataStoreContext | undefined {\n\t\tconst context = this._contexts.get(id);\n\t\tif (context === undefined || !this.notBoundContexts.has(id)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn context as LocalFluidDataStoreContext;\n\t}\n\n\t/**\n\t * Adds the given context to the collection, marking it as unbound (not yet locally visible).\n\t * Asserts that no context with this ID already exists.\n\t */\n\tpublic addUnbound(context: LocalFluidDataStoreContext): void {\n\t\tconst id = context.id;\n\t\tassert(!this._contexts.has(id), 0x158 /* \"Creating store with existing ID\" */);\n\n\t\tthis._contexts.set(id, context);\n\n\t\tthis.notBoundContexts.add(id);\n\t\tthis.ensureDeferred(id);\n\t}\n\n\t/**\n\t * Get the context with the given id, once it exists locally and is attached.\n\t * e.g. If created locally, it must be bound, or if created remotely then it's fine as soon as it's sync'd in.\n\t * @param id - The id of the context to get\n\t * @param wait - If false, return undefined if the context isn't present and ready now. Otherwise, wait for it.\n\t */\n\tpublic async getBoundOrRemoted(\n\t\tid: string,\n\t\twait: boolean,\n\t): Promise<FluidDataStoreContext | undefined> {\n\t\tconst deferredContext = this.ensureDeferred(id);\n\n\t\tif (!wait && !deferredContext.isCompleted) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn deferredContext.promise;\n\t}\n\n\t/**\n\t * Gets or creates a deferred promise for the given context ID.\n\t * Used to allow waiting for contexts that don't exist yet.\n\t */\n\tprivate ensureDeferred(id: string): Deferred<FluidDataStoreContext> {\n\t\tconst deferred = this.deferredContexts.get(id);\n\t\tif (deferred) {\n\t\t\treturn deferred;\n\t\t}\n\n\t\tconst newDeferred = new Deferred<FluidDataStoreContext>();\n\t\tthis.deferredContexts.set(id, newDeferred);\n\t\treturn newDeferred;\n\t}\n\n\t/**\n\t * Marks the context with the given ID as bound (locally visible).\n\t * Removes it from the unbound set and resolves its deferred promise.\n\t */\n\tpublic bind(id: string): void {\n\t\tconst removed: boolean = this.notBoundContexts.delete(id);\n\t\tassert(removed, 0x159 /* \"The given id was not found in notBoundContexts to delete\" */);\n\n\t\tthis.resolveDeferred(id);\n\t}\n\n\t/**\n\t * Triggers the deferred to resolve, indicating the context is not local-only\n\t * @param id - The id of the context to resolve to\n\t */\n\tprivate resolveDeferred(id: string): void {\n\t\tconst context = this._contexts.get(id);\n\t\tassert(!!context, 0x15a /* \"Cannot find context to resolve to\" */);\n\t\tassert(\n\t\t\t!this.notBoundContexts.has(id),\n\t\t\t0x15b /* \"Expected this id to already be removed from notBoundContexts\" */,\n\t\t);\n\n\t\tconst deferred = this.deferredContexts.get(id);\n\t\tassert(!!deferred, 0x15c /* \"Cannot find deferred to resolve\" */);\n\t\tdeferred.resolve(context);\n\t}\n\n\t/**\n\t * Adds the given context to the collection as already bound or from a remote client.\n\t * This is used when:\n\t * - Adding a local context that's already been bound via the bind() method, OR\n\t * - Adding a remote context that was created by another client.\n\t * The context's deferred promise is resolved immediately.\n\t */\n\tpublic addBoundOrRemoted(context: FluidDataStoreContext): void {\n\t\tconst id = context.id;\n\t\tassert(!this._contexts.has(id), 0x15d /* \"Creating store with existing ID\" */);\n\n\t\tthis._contexts.set(id, context);\n\n\t\t// Resolve the deferred immediately since this context is not unbound\n\t\tthis.ensureDeferred(id);\n\t\tthis.resolveDeferred(id);\n\t}\n}\n"]}
|
package/lib/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/container-runtime";
|
|
8
|
-
export declare const pkgVersion = "2.74.0
|
|
8
|
+
export declare const pkgVersion = "2.74.0";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,sCAAsC,CAAC;AAC3D,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,sCAAsC,CAAC;AAC3D,eAAO,MAAM,UAAU,WAAW,CAAC"}
|
package/lib/packageVersion.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,mCAAmC,CAAC;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,mCAAmC,CAAC;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-runtime\";\nexport const pkgVersion = \"2.74.0\";\n"]}
|
|
@@ -13,11 +13,11 @@ export declare const runtimeCoreCompatDetails: {
|
|
|
13
13
|
/**
|
|
14
14
|
* The package version of the Runtime layer.
|
|
15
15
|
*/
|
|
16
|
-
readonly pkgVersion: "2.74.0
|
|
16
|
+
readonly pkgVersion: "2.74.0";
|
|
17
17
|
/**
|
|
18
18
|
* The current generation of the Runtime layer.
|
|
19
19
|
*/
|
|
20
|
-
readonly generation:
|
|
20
|
+
readonly generation: 3;
|
|
21
21
|
};
|
|
22
22
|
/**
|
|
23
23
|
* Runtime's compatibility details that is exposed to the Loader layer.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtimeLayerCompatState.js","sourceRoot":"","sources":["../src/runtimeLayerCompatState.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EACN,+BAA+B,EAC/B,qBAAqB,GACrB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACN,0BAA0B,GAE1B,MAAM,0CAA0C,CAAC;AAElD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACvC;;OAEG;IACH,UAAU;IACV;;OAEG;IACH,UAAU,EAAE,CAAC;CACJ,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAwB;IACjE,GAAG,wBAAwB;IAC3B;;OAEG;IACH,iBAAiB,EAAE,IAAI,GAAG,EAAU;CACpC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAoC;IACnF;;;OAGG;IACH,sBAAsB,EAAE,CAAC;IACzB;;OAEG;IACH,gBAAgB,EAAE,EAAE;CACpB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAwB;IACpE,GAAG,wBAAwB;IAC3B;;OAEG;IACH,iBAAiB,EAAE,IAAI,GAAG,CAAS,CAAC,+BAA+B,EAAE,qBAAqB,CAAC,CAAC;CAC5F,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,sCAAsC,GAAoC;IACtF;;;OAGG;IACH,sBAAsB,EAAE,CAAC;IACzB;;OAEG;IACH,gBAAgB,EAAE,EAAE;CACpB,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CAC1C,kCAAmE,EACnE,SAAoD,EACpD,MAA2B;IAE3B,0BAA0B,CACzB,SAAS,EACT,QAAQ,EACR,6BAA6B,EAC7B,mCAAmC,EACnC,kCAAkC,EAClC,SAAS,EACT,MAAM,CACN,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,8BAA8B,CAC7C,qCAAsE,EACtE,SAAqB,EACrB,MAA2B;IAE3B,0BAA0B,CACzB,SAAS,EACT,WAAW,EACX,gCAAgC,EAChC,sCAAsC,EACtC,qCAAqC,EACrC,SAAS,EACT,MAAM,CACN,CAAC;AACH,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tILayerCompatDetails,\n\tILayerCompatSupportRequirements,\n} from \"@fluid-internal/client-utils\";\nimport type { ICriticalContainerError } from \"@fluidframework/container-definitions\";\nimport {\n\tencodeHandlesInContainerRuntime,\n\tnotifiesReadOnlyState,\n} from \"@fluidframework/runtime-definitions/internal\";\nimport {\n\tvalidateLayerCompatibility,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { pkgVersion } from \"./packageVersion.js\";\n\n/**\n * The core compatibility details of the Runtime layer that is the same across all layer boundaries.\n * @internal\n */\nexport const runtimeCoreCompatDetails = {\n\t/**\n\t * The package version of the Runtime layer.\n\t */\n\tpkgVersion,\n\t/**\n\t * The current generation of the Runtime layer.\n\t */\n\tgeneration:
|
|
1
|
+
{"version":3,"file":"runtimeLayerCompatState.js","sourceRoot":"","sources":["../src/runtimeLayerCompatState.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EACN,+BAA+B,EAC/B,qBAAqB,GACrB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACN,0BAA0B,GAE1B,MAAM,0CAA0C,CAAC;AAElD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACvC;;OAEG;IACH,UAAU;IACV;;OAEG;IACH,UAAU,EAAE,CAAC;CACJ,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAwB;IACjE,GAAG,wBAAwB;IAC3B;;OAEG;IACH,iBAAiB,EAAE,IAAI,GAAG,EAAU;CACpC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAoC;IACnF;;;OAGG;IACH,sBAAsB,EAAE,CAAC;IACzB;;OAEG;IACH,gBAAgB,EAAE,EAAE;CACpB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAwB;IACpE,GAAG,wBAAwB;IAC3B;;OAEG;IACH,iBAAiB,EAAE,IAAI,GAAG,CAAS,CAAC,+BAA+B,EAAE,qBAAqB,CAAC,CAAC;CAC5F,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,sCAAsC,GAAoC;IACtF;;;OAGG;IACH,sBAAsB,EAAE,CAAC;IACzB;;OAEG;IACH,gBAAgB,EAAE,EAAE;CACpB,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CAC1C,kCAAmE,EACnE,SAAoD,EACpD,MAA2B;IAE3B,0BAA0B,CACzB,SAAS,EACT,QAAQ,EACR,6BAA6B,EAC7B,mCAAmC,EACnC,kCAAkC,EAClC,SAAS,EACT,MAAM,CACN,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,8BAA8B,CAC7C,qCAAsE,EACtE,SAAqB,EACrB,MAA2B;IAE3B,0BAA0B,CACzB,SAAS,EACT,WAAW,EACX,gCAAgC,EAChC,sCAAsC,EACtC,qCAAqC,EACrC,SAAS,EACT,MAAM,CACN,CAAC;AACH,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tILayerCompatDetails,\n\tILayerCompatSupportRequirements,\n} from \"@fluid-internal/client-utils\";\nimport type { ICriticalContainerError } from \"@fluidframework/container-definitions\";\nimport {\n\tencodeHandlesInContainerRuntime,\n\tnotifiesReadOnlyState,\n} from \"@fluidframework/runtime-definitions/internal\";\nimport {\n\tvalidateLayerCompatibility,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { pkgVersion } from \"./packageVersion.js\";\n\n/**\n * The core compatibility details of the Runtime layer that is the same across all layer boundaries.\n * @internal\n */\nexport const runtimeCoreCompatDetails = {\n\t/**\n\t * The package version of the Runtime layer.\n\t */\n\tpkgVersion,\n\t/**\n\t * The current generation of the Runtime layer.\n\t */\n\tgeneration: 3,\n} as const;\n\n/**\n * Runtime's compatibility details that is exposed to the Loader layer.\n * @internal\n */\nexport const runtimeCompatDetailsForLoader: ILayerCompatDetails = {\n\t...runtimeCoreCompatDetails,\n\t/**\n\t * The features supported by the Runtime layer across the Runtime / Loader boundary.\n\t */\n\tsupportedFeatures: new Set<string>(),\n};\n\n/**\n * The requirements that the Loader layer must meet to be compatible with this Runtime.\n * @internal\n */\nexport const loaderSupportRequirementsForRuntime: ILayerCompatSupportRequirements = {\n\t/**\n\t * Minimum generation that Loader must be at to be compatible with Runtime. Note that 0 is used here so\n\t * that Loader layers before the introduction of the layer compatibility enforcement are compatible.\n\t */\n\tminSupportedGeneration: 0,\n\t/**\n\t * The features that the Loader must support to be compatible with Runtime.\n\t */\n\trequiredFeatures: [],\n};\n\n/**\n * Runtime's compatibility details that is exposed to the DataStore layer.\n * @internal\n */\nexport const runtimeCompatDetailsForDataStore: ILayerCompatDetails = {\n\t...runtimeCoreCompatDetails,\n\t/**\n\t * The features supported by the Runtime layer across the Runtime / DataStore boundary.\n\t */\n\tsupportedFeatures: new Set<string>([encodeHandlesInContainerRuntime, notifiesReadOnlyState]),\n};\n\n/**\n * The requirements that the DataStore layer must meet to be compatible with this Runtime.\n * @internal\n */\nexport const dataStoreSupportRequirementsForRuntime: ILayerCompatSupportRequirements = {\n\t/**\n\t * Minimum generation that DataStore must be at to be compatible with Runtime. Note that 0 is used here so\n\t * that DataStore layers before the introduction of the layer compatibility enforcement are compatible.\n\t */\n\tminSupportedGeneration: 0,\n\t/**\n\t * The features that the DataStore must support to be compatible with Runtime.\n\t */\n\trequiredFeatures: [],\n};\n\n/**\n * Validates that the Loader layer is compatible with this Runtime.\n * @internal\n */\nexport function validateLoaderCompatibility(\n\tmaybeLoaderCompatDetailsForRuntime: ILayerCompatDetails | undefined,\n\tdisposeFn: (error?: ICriticalContainerError) => void,\n\tlogger: ITelemetryLoggerExt,\n): void {\n\tvalidateLayerCompatibility(\n\t\t\"runtime\",\n\t\t\"loader\",\n\t\truntimeCompatDetailsForLoader,\n\t\tloaderSupportRequirementsForRuntime,\n\t\tmaybeLoaderCompatDetailsForRuntime,\n\t\tdisposeFn,\n\t\tlogger,\n\t);\n}\n\n/**\n * Validates that the DataStore layer is compatible with this Runtime.\n * @internal\n */\nexport function validateDatastoreCompatibility(\n\tmaybeDataStoreCompatDetailsForRuntime: ILayerCompatDetails | undefined,\n\tdisposeFn: () => void,\n\tlogger: ITelemetryLoggerExt,\n): void {\n\tvalidateLayerCompatibility(\n\t\t\"runtime\",\n\t\t\"dataStore\",\n\t\truntimeCompatDetailsForDataStore,\n\t\tdataStoreSupportRequirementsForRuntime,\n\t\tmaybeDataStoreCompatDetailsForRuntime,\n\t\tdisposeFn,\n\t\tlogger,\n\t);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/container-runtime",
|
|
3
|
-
"version": "2.74.0
|
|
3
|
+
"version": "2.74.0",
|
|
4
4
|
"description": "Fluid container runtime",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -119,18 +119,18 @@
|
|
|
119
119
|
"temp-directory": "nyc/.nyc_output"
|
|
120
120
|
},
|
|
121
121
|
"dependencies": {
|
|
122
|
-
"@fluid-internal/client-utils": "2.74.0
|
|
123
|
-
"@fluidframework/container-definitions": "2.74.0
|
|
124
|
-
"@fluidframework/container-runtime-definitions": "2.74.0
|
|
125
|
-
"@fluidframework/core-interfaces": "2.74.0
|
|
126
|
-
"@fluidframework/core-utils": "2.74.0
|
|
127
|
-
"@fluidframework/datastore": "2.74.0
|
|
128
|
-
"@fluidframework/driver-definitions": "2.74.0
|
|
129
|
-
"@fluidframework/driver-utils": "2.74.0
|
|
130
|
-
"@fluidframework/id-compressor": "2.74.0
|
|
131
|
-
"@fluidframework/runtime-definitions": "2.74.0
|
|
132
|
-
"@fluidframework/runtime-utils": "2.74.0
|
|
133
|
-
"@fluidframework/telemetry-utils": "2.74.0
|
|
122
|
+
"@fluid-internal/client-utils": "~2.74.0",
|
|
123
|
+
"@fluidframework/container-definitions": "~2.74.0",
|
|
124
|
+
"@fluidframework/container-runtime-definitions": "~2.74.0",
|
|
125
|
+
"@fluidframework/core-interfaces": "~2.74.0",
|
|
126
|
+
"@fluidframework/core-utils": "~2.74.0",
|
|
127
|
+
"@fluidframework/datastore": "~2.74.0",
|
|
128
|
+
"@fluidframework/driver-definitions": "~2.74.0",
|
|
129
|
+
"@fluidframework/driver-utils": "~2.74.0",
|
|
130
|
+
"@fluidframework/id-compressor": "~2.74.0",
|
|
131
|
+
"@fluidframework/runtime-definitions": "~2.74.0",
|
|
132
|
+
"@fluidframework/runtime-utils": "~2.74.0",
|
|
133
|
+
"@fluidframework/telemetry-utils": "~2.74.0",
|
|
134
134
|
"@tylerbu/sorted-btree-es6": "^1.8.0",
|
|
135
135
|
"double-ended-queue": "^2.1.0-0",
|
|
136
136
|
"lz4js": "^0.2.0",
|
|
@@ -140,16 +140,16 @@
|
|
|
140
140
|
"devDependencies": {
|
|
141
141
|
"@arethetypeswrong/cli": "^0.17.1",
|
|
142
142
|
"@biomejs/biome": "~1.9.3",
|
|
143
|
-
"@fluid-internal/mocha-test-setup": "2.74.0
|
|
144
|
-
"@fluid-private/stochastic-test-utils": "2.74.0
|
|
145
|
-
"@fluid-private/test-pairwise-generator": "2.74.0
|
|
143
|
+
"@fluid-internal/mocha-test-setup": "~2.74.0",
|
|
144
|
+
"@fluid-private/stochastic-test-utils": "~2.74.0",
|
|
145
|
+
"@fluid-private/test-pairwise-generator": "~2.74.0",
|
|
146
146
|
"@fluid-tools/benchmark": "^0.51.0",
|
|
147
|
-
"@fluid-tools/build-cli": "^0.
|
|
147
|
+
"@fluid-tools/build-cli": "^0.61.0",
|
|
148
148
|
"@fluidframework/build-common": "^2.0.3",
|
|
149
|
-
"@fluidframework/build-tools": "^0.
|
|
149
|
+
"@fluidframework/build-tools": "^0.61.0",
|
|
150
150
|
"@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.73.0",
|
|
151
|
-
"@fluidframework/eslint-config-fluid": "2.74.0
|
|
152
|
-
"@fluidframework/test-runtime-utils": "2.74.0
|
|
151
|
+
"@fluidframework/eslint-config-fluid": "~2.74.0",
|
|
152
|
+
"@fluidframework/test-runtime-utils": "~2.74.0",
|
|
153
153
|
"@microsoft/api-extractor": "7.52.11",
|
|
154
154
|
"@types/double-ended-queue": "^2.1.0",
|
|
155
155
|
"@types/lz4js": "^0.2.0",
|
|
@@ -161,6 +161,7 @@
|
|
|
161
161
|
"copyfiles": "^2.4.1",
|
|
162
162
|
"cross-env": "^7.0.3",
|
|
163
163
|
"eslint": "~8.57.1",
|
|
164
|
+
"jiti": "^2.6.1",
|
|
164
165
|
"mocha": "^10.8.2",
|
|
165
166
|
"mocha-multi-reporters": "^1.5.1",
|
|
166
167
|
"rimraf": "^4.4.0",
|
package/src/channelCollection.ts
CHANGED
|
@@ -492,9 +492,33 @@ export class ChannelCollection
|
|
|
492
492
|
continue;
|
|
493
493
|
}
|
|
494
494
|
|
|
495
|
-
//
|
|
495
|
+
// Check for collision with local (not yet live / known to other clients) DataStore
|
|
496
|
+
// This is not a DataCorruption case if we crash the container before the DataStore becomes visible to others (it's a DataProcessingError instead)
|
|
497
|
+
//
|
|
498
|
+
// POSSIBLE CAUSES:
|
|
499
|
+
// - Something with ID creation, e.g. a bug in shortID logic, or somehow a generated ID matches an existing alias.
|
|
500
|
+
// - An invalid operation by the application or service where an existing container is returned to a new container attach call,
|
|
501
|
+
// resulting in duplicate accounting for objects that were supposed to be local-only. e.g. if the application patches in custom
|
|
502
|
+
// logic not supported by Fluid's API.
|
|
503
|
+
if (this.contexts.getUnbound(attachMessage.id) !== undefined) {
|
|
504
|
+
const error = DataProcessingError.create(
|
|
505
|
+
"Local DataStore matches remote DataStore id",
|
|
506
|
+
"DataStoreAttach",
|
|
507
|
+
envelope,
|
|
508
|
+
{ ...tagCodeArtifacts({ dataStoreId: attachMessage.id }) },
|
|
509
|
+
);
|
|
510
|
+
throw error;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Check for collision with already processed (attaching/attached or aliased) DataStore
|
|
514
|
+
// This is presumed to indicate a corrupted op stream, where we'd expect all future sessions to fail here too.
|
|
515
|
+
//
|
|
516
|
+
// POSSIBLE CAUSES:
|
|
517
|
+
// - A bug in the service or driver that results in ops being duplicated
|
|
518
|
+
// - Similar to above, an existing container being returned to a new container attach call,
|
|
519
|
+
// where the DataStore in question was already made locally visible before container attach.
|
|
520
|
+
// (Perhaps future sessions would not fail in this case, but it's hypothetical and hard to differentiate)
|
|
496
521
|
if (this.alreadyProcessed(attachMessage.id)) {
|
|
497
|
-
// TODO: dataStoreId may require a different tag from PackageData #7488
|
|
498
522
|
const error = new DataCorruptionError(
|
|
499
523
|
// pre-0.58 error message: duplicateDataStoreCreatedWithExistingId
|
|
500
524
|
"Duplicate DataStore created with existing id",
|