@fluidframework/agent-scheduler 2.53.0 → 2.60.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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # @fluidframework/agent-scheduler
2
2
 
3
+ ## 2.60.0
4
+
5
+ Dependency updates only.
6
+
3
7
  ## 2.53.0
4
8
 
5
9
  Dependency updates only.
@@ -1,10 +1,10 @@
1
- ## Alpha API Report File for "@fluidframework/agent-scheduler"
1
+ ## Beta API Report File for "@fluidframework/agent-scheduler"
2
2
 
3
3
  > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
4
4
 
5
5
  ```ts
6
6
 
7
- // @alpha @legacy (undocumented)
7
+ // @beta @legacy (undocumented)
8
8
  export class AgentSchedulerFactory implements IFluidDataStoreFactory {
9
9
  // (undocumented)
10
10
  static createChildInstance(parentContext: IFluidDataStoreContext): Promise<IAgentScheduler>;
@@ -20,10 +20,10 @@ export class AgentSchedulerFactory implements IFluidDataStoreFactory {
20
20
  readonly type = "_scheduler";
21
21
  }
22
22
 
23
- // @alpha @legacy (undocumented)
23
+ // @beta @legacy (undocumented)
24
24
  export const IAgentScheduler: keyof IProvideAgentScheduler;
25
25
 
26
- // @alpha @legacy
26
+ // @beta @legacy
27
27
  export interface IAgentScheduler extends IProvideAgentScheduler, IEventProvider<IAgentSchedulerEvents>, IFluidLoadable {
28
28
  pick(taskId: string, worker: () => Promise<void>): Promise<void>;
29
29
  pickedTasks(): string[];
@@ -31,24 +31,24 @@ export interface IAgentScheduler extends IProvideAgentScheduler, IEventProvider<
31
31
  release(...taskUrls: string[]): Promise<void>;
32
32
  }
33
33
 
34
- // @alpha @legacy
34
+ // @beta @legacy
35
35
  export interface IAgentSchedulerEvents extends IEvent {
36
36
  (event: "picked" | "released" | "lost", listener: (taskId: string) => void): any;
37
37
  }
38
38
 
39
- // @alpha @legacy (undocumented)
39
+ // @beta @legacy (undocumented)
40
40
  export interface IProvideAgentScheduler {
41
41
  // (undocumented)
42
42
  readonly IAgentScheduler: IAgentScheduler;
43
43
  }
44
44
 
45
- // @alpha @legacy
45
+ // @beta @legacy
46
46
  export interface ITaskSubscriptionEvents extends IEvent {
47
47
  // (undocumented)
48
48
  (event: "gotTask" | "lostTask", listener: () => void): any;
49
49
  }
50
50
 
51
- // @alpha @legacy
51
+ // @beta @legacy
52
52
  export class TaskSubscription extends TypedEventEmitter<ITaskSubscriptionEvents> {
53
53
  constructor(agentScheduler: IAgentScheduler, taskId: string);
54
54
  haveTask(): boolean;
package/dist/agent.d.ts CHANGED
@@ -5,12 +5,12 @@
5
5
  import type { IEvent, IEventProvider, IFluidLoadable } from "@fluidframework/core-interfaces";
6
6
  /**
7
7
  * @legacy
8
- * @alpha
8
+ * @beta
9
9
  */
10
10
  export declare const IAgentScheduler: keyof IProvideAgentScheduler;
11
11
  /**
12
12
  * @legacy
13
- * @alpha
13
+ * @beta
14
14
  */
15
15
  export interface IProvideAgentScheduler {
16
16
  readonly IAgentScheduler: IAgentScheduler;
@@ -18,7 +18,7 @@ export interface IProvideAgentScheduler {
18
18
  /**
19
19
  * Events emitted by {@link (IAgentScheduler:interface)}.
20
20
  * @legacy
21
- * @alpha
21
+ * @beta
22
22
  */
23
23
  export interface IAgentSchedulerEvents extends IEvent {
24
24
  /**
@@ -43,7 +43,7 @@ export interface IAgentSchedulerEvents extends IEvent {
43
43
  /**
44
44
  * Agent scheduler distributes a set of tasks/variables across connected clients.
45
45
  * @legacy
46
- * @alpha
46
+ * @beta
47
47
  */
48
48
  export interface IAgentScheduler extends IProvideAgentScheduler, IEventProvider<IAgentSchedulerEvents>, IFluidLoadable {
49
49
  /**
package/dist/agent.js CHANGED
@@ -7,7 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.IAgentScheduler = void 0;
8
8
  /**
9
9
  * @legacy
10
- * @alpha
10
+ * @beta
11
11
  */
12
12
  exports.IAgentScheduler = "IAgentScheduler";
13
13
  //# sourceMappingURL=agent.js.map
package/dist/agent.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH;;;GAGG;AACU,QAAA,eAAe,GAAiC,iBAAiB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IEvent, IEventProvider, IFluidLoadable } from \"@fluidframework/core-interfaces\";\n\n/**\n * @legacy\n * @alpha\n */\nexport const IAgentScheduler: keyof IProvideAgentScheduler = \"IAgentScheduler\";\n\n/**\n * @legacy\n * @alpha\n */\nexport interface IProvideAgentScheduler {\n\treadonly IAgentScheduler: IAgentScheduler;\n}\n\n/**\n * Events emitted by {@link (IAgentScheduler:interface)}.\n * @legacy\n * @alpha\n */\nexport interface IAgentSchedulerEvents extends IEvent {\n\t/**\n\t * Event when ownership of task changes\n\t * @param event - name of the event:\n\t *\n\t * - \"picked\" - the task has been assigned to this client, in response to pick() being called\n\t * If client loses this task (due to disconnect), it will attempt to pick it again (on connection)\n\t * automatically, unless release() is called\n\t *\n\t * - \"released\" - the task was successfully released back to the pool. Client will not attempt to\n\t * re-acquire the task, unless pick() is called.\n\t *\n\t * - \"lost\" - task is lost due to disconnect or data store / container being attached.\n\t * Task will be picked up again by some connected client (this client will try as well,\n\t * unless release() is called)\n\t *\n\t * @param listener - callback notified when change happened for particular key\n\t */\n\t(event: \"picked\" | \"released\" | \"lost\", listener: (taskId: string) => void);\n}\n\n/**\n * Agent scheduler distributes a set of tasks/variables across connected clients.\n * @legacy\n * @alpha\n */\nexport interface IAgentScheduler\n\textends IProvideAgentScheduler,\n\t\tIEventProvider<IAgentSchedulerEvents>,\n\t\tIFluidLoadable {\n\t/**\n\t * Registers a set of new tasks to distribute amongst connected clients. Only use this if a client wants\n\t * a new agent to run but does not have the capability to run the agent inside the host.\n\t * Client can call pick() later if the capability changes.\n\t *\n\t * This method should only be called once per task. Duplicate calls will be rejected.\n\t */\n\tregister(...taskUrls: string[]): Promise<void>;\n\n\t/**\n\t * Attempts to pick a set of tasks. A client will only run the task if it's chosen based on consensus.\n\t * Resolves when the tasks are assigned to one of the connected clients.\n\t *\n\t * This method should only be called once per task. Duplicate calls will be rejected.\n\t *\n\t * @param worker - callback to run when task is picked up.\n\t */\n\tpick(taskId: string, worker: () => Promise<void>): Promise<void>;\n\n\t/**\n\t * Releases a set of tasks for other clients to grab. Resolves when the tasks are released.\n\t *\n\t * Only previously picked tasks are allowed. Releasing non picked tasks will get a rejection.\n\t * App can call pickedTasks() to get the picked list first.\n\t */\n\trelease(...taskUrls: string[]): Promise<void>;\n\n\t/**\n\t * Returns a list of all tasks running on this client\n\t */\n\tpickedTasks(): string[];\n}\n"]}
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH;;;GAGG;AACU,QAAA,eAAe,GAAiC,iBAAiB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IEvent, IEventProvider, IFluidLoadable } from \"@fluidframework/core-interfaces\";\n\n/**\n * @legacy\n * @beta\n */\nexport const IAgentScheduler: keyof IProvideAgentScheduler = \"IAgentScheduler\";\n\n/**\n * @legacy\n * @beta\n */\nexport interface IProvideAgentScheduler {\n\treadonly IAgentScheduler: IAgentScheduler;\n}\n\n/**\n * Events emitted by {@link (IAgentScheduler:interface)}.\n * @legacy\n * @beta\n */\nexport interface IAgentSchedulerEvents extends IEvent {\n\t/**\n\t * Event when ownership of task changes\n\t * @param event - name of the event:\n\t *\n\t * - \"picked\" - the task has been assigned to this client, in response to pick() being called\n\t * If client loses this task (due to disconnect), it will attempt to pick it again (on connection)\n\t * automatically, unless release() is called\n\t *\n\t * - \"released\" - the task was successfully released back to the pool. Client will not attempt to\n\t * re-acquire the task, unless pick() is called.\n\t *\n\t * - \"lost\" - task is lost due to disconnect or data store / container being attached.\n\t * Task will be picked up again by some connected client (this client will try as well,\n\t * unless release() is called)\n\t *\n\t * @param listener - callback notified when change happened for particular key\n\t */\n\t(event: \"picked\" | \"released\" | \"lost\", listener: (taskId: string) => void);\n}\n\n/**\n * Agent scheduler distributes a set of tasks/variables across connected clients.\n * @legacy\n * @beta\n */\nexport interface IAgentScheduler\n\textends IProvideAgentScheduler,\n\t\tIEventProvider<IAgentSchedulerEvents>,\n\t\tIFluidLoadable {\n\t/**\n\t * Registers a set of new tasks to distribute amongst connected clients. Only use this if a client wants\n\t * a new agent to run but does not have the capability to run the agent inside the host.\n\t * Client can call pick() later if the capability changes.\n\t *\n\t * This method should only be called once per task. Duplicate calls will be rejected.\n\t */\n\tregister(...taskUrls: string[]): Promise<void>;\n\n\t/**\n\t * Attempts to pick a set of tasks. A client will only run the task if it's chosen based on consensus.\n\t * Resolves when the tasks are assigned to one of the connected clients.\n\t *\n\t * This method should only be called once per task. Duplicate calls will be rejected.\n\t *\n\t * @param worker - callback to run when task is picked up.\n\t */\n\tpick(taskId: string, worker: () => Promise<void>): Promise<void>;\n\n\t/**\n\t * Releases a set of tasks for other clients to grab. Resolves when the tasks are released.\n\t *\n\t * Only previously picked tasks are allowed. Releasing non picked tasks will get a rejection.\n\t * App can call pickedTasks() to get the picked list first.\n\t */\n\trelease(...taskUrls: string[]): Promise<void>;\n\n\t/**\n\t * Returns a list of all tasks running on this client\n\t */\n\tpickedTasks(): string[];\n}\n"]}
@@ -43,7 +43,7 @@ export declare class AgentScheduler extends TypedEventEmitter<IAgentSchedulerEve
43
43
  }
44
44
  /**
45
45
  * @legacy
46
- * @alpha
46
+ * @beta
47
47
  */
48
48
  export declare class AgentSchedulerFactory implements IFluidDataStoreFactory {
49
49
  static readonly type = "_scheduler";
package/dist/scheduler.js CHANGED
@@ -376,7 +376,7 @@ class AgentSchedulerRuntime extends internal_2.FluidDataStoreRuntime {
376
376
  }
377
377
  /**
378
378
  * @legacy
379
- * @alpha
379
+ * @beta
380
380
  */
381
381
  class AgentSchedulerFactory {
382
382
  constructor() {
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.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 { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport type {\n\tFluidObject,\n\tIFluidHandle,\n\tIFluidLoadable,\n\tIRequest,\n\tIResponse,\n} from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport {\n\tFluidDataStoreRuntime,\n\tFluidObjectHandle,\n\ttype ISharedObjectRegistry,\n} from \"@fluidframework/datastore/internal\";\nimport type {\n\tIChannelFactory,\n\tIFluidDataStoreRuntime,\n} from \"@fluidframework/datastore-definitions/internal\";\nimport { type ISharedMap, type IValueChanged, SharedMap } from \"@fluidframework/map/internal\";\nimport { ConsensusRegisterCollection } from \"@fluidframework/register-collection/internal\";\nimport type {\n\tIFluidDataStoreContext,\n\tIFluidDataStoreFactory,\n\tNamedFluidDataStoreRegistryEntry,\n} from \"@fluidframework/runtime-definitions/internal\";\nimport {\n\ttype ITelemetryLoggerExt,\n\tUsageError,\n\tcreateChildLogger,\n\ttagCodeArtifacts,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { v4 as uuid } from \"uuid\";\n\nimport type { IAgentScheduler, IAgentSchedulerEvents } from \"./agent.js\";\n\n// Note: making sure this ID is unique and does not collide with storage provided clientID\nconst UnattachedClientId = `${uuid()}_unattached`;\n\nconst mapWait = async <T = unknown>(map: ISharedMap, key: string): Promise<T> => {\n\tconst maybeValue = map.get<T>(key);\n\tif (maybeValue !== undefined) {\n\t\treturn maybeValue;\n\t}\n\n\treturn new Promise((resolve) => {\n\t\tconst handler = (changed: IValueChanged): void => {\n\t\t\tif (changed.key === key) {\n\t\t\t\tmap.off(\"valueChanged\", handler);\n\t\t\t\tconst value = map.get<T>(changed.key);\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tthrow new Error(\"Unexpected valueChanged result\");\n\t\t\t\t}\n\t\t\t\tresolve(value);\n\t\t\t}\n\t\t};\n\t\tmap.on(\"valueChanged\", handler);\n\t});\n};\n\nconst schedulerId = \"scheduler\";\n\nexport class AgentScheduler\n\textends TypedEventEmitter<IAgentSchedulerEvents>\n\timplements IAgentScheduler\n{\n\tpublic static async load(\n\t\truntime: IFluidDataStoreRuntime,\n\t\tcontext: IFluidDataStoreContext,\n\t\texisting: boolean,\n\t): Promise<IAgentScheduler> {\n\t\tlet root: ISharedMap;\n\t\tlet consensusRegisterCollection: ConsensusRegisterCollection<string | null>;\n\t\tif (existing) {\n\t\t\troot = (await runtime.getChannel(\"root\")) as ISharedMap;\n\t\t\tconst handle = await mapWait<IFluidHandle<ConsensusRegisterCollection<string | null>>>(\n\t\t\t\troot,\n\t\t\t\tschedulerId,\n\t\t\t);\n\t\t\tassert(handle !== undefined, 0x116 /* \"Missing handle on scheduler load\" */);\n\t\t\tconsensusRegisterCollection = await handle.get();\n\t\t} else {\n\t\t\troot = SharedMap.create(runtime, \"root\");\n\t\t\troot.bindToContext();\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\tconsensusRegisterCollection = ConsensusRegisterCollection.create(runtime);\n\t\t\tconsensusRegisterCollection.bindToContext();\n\t\t\troot.set(schedulerId, consensusRegisterCollection.handle);\n\t\t}\n\t\tconst agentScheduler = new AgentScheduler(runtime, context, consensusRegisterCollection);\n\t\tagentScheduler.initialize();\n\n\t\treturn agentScheduler;\n\t}\n\n\tpublic get IAgentScheduler(): IAgentScheduler {\n\t\treturn this;\n\t}\n\tpublic get IFluidLoadable(): IFluidLoadable {\n\t\treturn this;\n\t}\n\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tprivate get clientId(): string {\n\t\tif (this.runtime.attachState === AttachState.Detached) {\n\t\t\treturn UnattachedClientId;\n\t\t}\n\t\tconst clientId = this.runtime.clientId;\n\t\tassert(!!clientId, 0x117 /* \"Trying to get missing clientId!\" */);\n\t\treturn clientId;\n\t}\n\n\t// Set of tasks registered by this client.\n\t// Has no relationship with lists below.\n\t// The only requirement here - a task can be registered by a client only once.\n\t// Other clients can pick these tasks.\n\tprivate readonly registeredTasks = new Set<string>();\n\n\t// List of all tasks client is capable of running (essentially expressed desire to run)\n\t// Client will proactively attempt to pick them up these tasks if they are not assigned to other clients.\n\t// This is a strict superset of tasks running in the client.\n\tprivate readonly locallyRunnableTasks = new Map<string, () => Promise<void>>();\n\n\t// Set of registered tasks client is currently running.\n\t// It's subset of this.locallyRunnableTasks\n\tprivate runningTasks = new Set<string>();\n\n\tprivate readonly _handle: IFluidHandle<this>;\n\n\tconstructor(\n\t\tprivate readonly runtime: IFluidDataStoreRuntime,\n\t\tprivate readonly context: IFluidDataStoreContext,\n\t\tprivate readonly consensusRegisterCollection: ConsensusRegisterCollection<string | null>,\n\t) {\n\t\tsuper();\n\t\tthis.logger = createChildLogger({ logger: runtime.logger });\n\t\t// We are expecting this class to have many listeners, so we suppress noisy \"MaxListenersExceededWarning\" logging.\n\t\tsuper.setMaxListeners(0);\n\t\tthis._handle = new FluidObjectHandle(this, \"\", this.runtime.objectsRoutingContext);\n\t}\n\n\tpublic get handle(): IFluidHandle<this> {\n\t\treturn this._handle;\n\t}\n\n\tpublic async register(...taskUrls: string[]): Promise<void> {\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tif (this.registeredTasks.has(taskUrl)) {\n\t\t\t\tthrow new UsageError(`Task is already registered`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t}\n\t\tconst unregisteredTasks: string[] = [];\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tthis.registeredTasks.add(taskUrl);\n\t\t\t// Only register for a new task.\n\t\t\tconst currentClient = this.getTaskClientId(taskUrl);\n\t\t\tif (currentClient === undefined) {\n\t\t\t\tunregisteredTasks.push(taskUrl);\n\t\t\t}\n\t\t}\n\t\treturn this.registerCore(unregisteredTasks);\n\t}\n\n\tpublic async pick(taskUrl: string, worker: () => Promise<void>): Promise<void> {\n\t\tif (this.locallyRunnableTasks.has(taskUrl)) {\n\t\t\tthrow new UsageError(`Task is already attempted`, tagCodeArtifacts({ taskUrl }));\n\t\t}\n\t\tthis.locallyRunnableTasks.set(taskUrl, worker);\n\n\t\t// We have a policy to disallow non-interactive clients from taking tasks. Callers of pick() can\n\t\t// either perform this check proactively and call conditionally, or catch the error (in which case\n\t\t// they can know they will not get the task).\n\t\tassert(\n\t\t\tthis.context.deltaManager.clientDetails.capabilities.interactive,\n\t\t\t0x118 /* \"Bad client interactive check\" */,\n\t\t);\n\n\t\t// Check the current status and express interest if it's a new one (undefined) or currently unpicked (null).\n\t\tif (this.isActive()) {\n\t\t\tconst currentClient = this.getTaskClientId(taskUrl);\n\t\t\tif (currentClient === undefined || currentClient === null) {\n\t\t\t\tawait this.writeCore(taskUrl, this.clientId);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async release(...taskUrls: string[]): Promise<void> {\n\t\tconst active = this.isActive();\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tif (!this.locallyRunnableTasks.has(taskUrl)) {\n\t\t\t\tthrow new UsageError(`Task was never registered`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t\tif (!this.runningTasks.has(taskUrl)) {\n\t\t\t\t// If we got disconnected (and are attached), tasks that we WERE picked for at the time of disconnect\n\t\t\t\t// will still show us as holding the task according to getTaskClientId (the CRC is stale), but we\n\t\t\t\t// should not try to release because our disconnect will already result in either someone else or\n\t\t\t\t// ourselves clearing the task upon reconnect.\n\t\t\t\t// This UsageError is to enforce that the caller should check AgentScheduler.pickedTasks before trying\n\t\t\t\t// to release a task.\n\t\t\t\tthrow new UsageError(`Task is not currently picked`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t\t// We may only release tasks that we KNOW we hold (detached state or connected and own the CRC). If we're\n\t\t\t// attached+disconnected then we'll lose the task automatically, and so may not release manually (someone\n\t\t\t// else might hold it by the time we reconnect)\n\t\t\tassert(active, 0x119 /* \"This agent became inactive while releasing\" */);\n\t\t\tif (this.getTaskClientId(taskUrl) !== this.clientId) {\n\t\t\t\tthrow new UsageError(`Task was never picked`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t}\n\t\treturn this.releaseCore([...taskUrls]);\n\t}\n\n\tpublic pickedTasks(): string[] {\n\t\treturn [...this.runningTasks.values()];\n\t}\n\t/* eslint-disable unicorn/no-null */\n\tprivate async registerCore(taskUrls: string[]): Promise<void> {\n\t\tif (taskUrls.length > 0) {\n\t\t\tconst registersP: Promise<void>[] = [];\n\t\t\tfor (const taskUrl of taskUrls) {\n\t\t\t\tregistersP.push(this.writeCore(taskUrl, null));\n\t\t\t}\n\t\t\tawait Promise.all(registersP);\n\n\t\t\t// The registers should have up to date results now. Check the status.\n\t\t\tfor (const taskUrl of taskUrls) {\n\t\t\t\tconst taskStatus = this.getTaskClientId(taskUrl);\n\n\t\t\t\t// Task should be either registered (null) or picked up.\n\t\t\t\tassert(taskStatus !== undefined, 0x11a /* `Unsuccessful registration` */);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async releaseCore(taskUrls: string[]): Promise<void> {\n\t\tif (taskUrls.length > 0) {\n\t\t\tconst releasesP: Promise<void>[] = [];\n\t\t\tfor (const taskUrl of taskUrls) {\n\t\t\t\t// Remove from local map so that it can be picked later.\n\t\t\t\tthis.locallyRunnableTasks.delete(taskUrl);\n\t\t\t\treleasesP.push(this.writeCore(taskUrl, null));\n\t\t\t}\n\t\t\tawait Promise.all(releasesP);\n\t\t}\n\t}\n\n\tprivate async clearTasks(taskUrls: string[]): Promise<void> {\n\t\tassert(this.isActive(), 0x11b /* \"Trying to clear tasks on inactive agent\" */);\n\t\tconst clearP: Promise<void>[] = [];\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tclearP.push(this.writeCore(taskUrl, null));\n\t\t}\n\t\tawait Promise.all(clearP);\n\t}\n\n\tprivate getTaskClientId(url: string): string | null | undefined {\n\t\treturn this.consensusRegisterCollection.read(url);\n\t}\n\n\tprivate async writeCore(key: string, clientId: string | null): Promise<void> {\n\t\tawait this.consensusRegisterCollection.write(key, clientId);\n\t}\n\n\tprivate initialize(): void {\n\t\tconst quorum = this.runtime.getQuorum();\n\t\t// A client left the quorum. Iterate and clear tasks held by that client.\n\t\t// Ideally a leader should do this cleanup. But it's complicated when a leader itself leaves.\n\t\t// Probably okay for now to have every client try to do this.\n\t\t// eslint-disable-next-line @typescript-eslint/no-misused-promises\n\t\tquorum.on(\"removeMember\", async (clientId: string) => {\n\t\t\t// TODO AB#19980: The scenario with a detached routing context is not fully supported.\n\t\t\tif (!this.runtime.objectsRoutingContext.isAttached) return;\n\t\t\t// Cleanup only if connected. If not, cleanup will happen in initializeCore() that runs on connection.\n\t\t\tif (this.isActive()) {\n\t\t\t\tconst tasks: Promise<unknown>[] = [];\n\t\t\t\tconst leftTasks: string[] = [];\n\t\t\t\tfor (const taskUrl of this.consensusRegisterCollection.keys()) {\n\t\t\t\t\tif (this.getTaskClientId(taskUrl) === clientId) {\n\t\t\t\t\t\tif (this.locallyRunnableTasks.has(taskUrl)) {\n\t\t\t\t\t\t\ttasks.push(this.writeCore(taskUrl, this.clientId));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tleftTasks.push(taskUrl);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttasks.push(this.clearTasks(leftTasks));\n\t\t\t\tawait Promise.all(tasks).catch((error) => {\n\t\t\t\t\tthis.sendErrorEvent(\"AgentScheduler_RemoveMemberError\", error);\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\t// Listeners for new/released tasks. All clients will try to grab at the same time.\n\t\t// May be we want a randomized timer (Something like raft) to reduce chattiness?\n\t\tthis.consensusRegisterCollection.on(\n\t\t\t\"atomicChanged\",\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-misused-promises\n\t\t\tasync (key: string, currentClient: string | null) => {\n\t\t\t\t// Check if this client was chosen.\n\t\t\t\tif (this.isActive() && currentClient === this.clientId) {\n\t\t\t\t\tthis.onNewTaskAssigned(key);\n\t\t\t\t} else {\n\t\t\t\t\t// The call below mutates the consensusRegisterCollection in\n\t\t\t\t\t// its event handler, which is not safe.\n\t\t\t\t\t// We need to force this to be part of a different batch of ops by\n\t\t\t\t\t// scheduling a microtask in order to work around the current validations.\n\t\t\t\t\t// This is not recommended and should be avoided.\n\t\t\t\t\tawait Promise.resolve().then(async () => {\n\t\t\t\t\t\tawait this.onTaskReassigned(key, currentClient);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\tif (this.isActive()) {\n\t\t\tthis.initializeCore();\n\t\t}\n\n\t\tthis.runtime.on(\"connected\", () => {\n\t\t\tif (this.isActive()) {\n\t\t\t\tthis.initializeCore();\n\t\t\t}\n\t\t});\n\n\t\tif (this.runtime.attachState === AttachState.Detached) {\n\t\t\tthis.runtime\n\t\t\t\t.waitAttached()\n\t\t\t\t.then(() => {\n\t\t\t\t\tthis.clearRunningTasks();\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tthis.sendErrorEvent(\"AgentScheduler_clearRunningTasks\", error);\n\t\t\t\t});\n\t\t}\n\n\t\tthis.runtime.on(\"disconnected\", () => {\n\t\t\tif (this.runtime.attachState !== AttachState.Detached) {\n\t\t\t\tthis.clearRunningTasks();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate onNewTaskAssigned(key: string): void {\n\t\tassert(!this.runningTasks.has(key), 0x11d /* \"task is already running\" */);\n\t\tthis.runningTasks.add(key);\n\t\tconst worker = this.locallyRunnableTasks.get(key);\n\t\tif (worker === undefined) {\n\t\t\tthis.sendErrorEvent(\"AgentScheduler_UnwantedChange\", undefined, key);\n\t\t} else {\n\t\t\tthis.emit(\"picked\", key);\n\t\t\tworker().catch((error) => {\n\t\t\t\tthis.sendErrorEvent(\"AgentScheduler_FailedWork\", error, key);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async onTaskReassigned(key: string, currentClient: string | null): Promise<void> {\n\t\tif (this.runningTasks.has(key)) {\n\t\t\tthis.runningTasks.delete(key);\n\t\t\tthis.emit(\"released\", key);\n\t\t}\n\t\tassert(currentClient !== undefined, 0x11e /* \"client is undefined\" */);\n\t\tif (this.isActive()) {\n\t\t\t// attempt to pick up task if we are connected.\n\t\t\t// If not, initializeCore() will do it when connected\n\t\t\tif (currentClient === null) {\n\t\t\t\tif (this.locallyRunnableTasks.has(key)) {\n\t\t\t\t\tawait this.writeCore(key, this.clientId);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Check if the op came from dropped client\n\t\t\t// This could happen when \"old\" ops are submitted on reconnection.\n\t\t\t// They carry \"old\" ref seq number, but if write is not contested, it will get accepted\n\t\t\telse if (this.runtime.getQuorum().getMember(currentClient) === undefined) {\n\t\t\t\tawait this.writeCore(key, null);\n\t\t\t}\n\t\t}\n\t}\n\t/* eslint-enable unicorn/no-null */\n\n\tprivate isActive(): boolean {\n\t\t// Scheduler should be active in detached container.\n\t\tif (this.runtime.attachState === AttachState.Detached) {\n\t\t\treturn true;\n\t\t}\n\t\tif (!this.runtime.connected) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Note: we are not checking for this.context.deltaManager.clientDetails.capabilities.interactive\n\t\t// here. Instead we assert in pick() if a non-interactive client tries to pick.\n\n\t\treturn this.context.deltaManager.active;\n\t}\n\n\tprivate initializeCore(): void {\n\t\t// Nobody released the tasks held by last client in previous session.\n\t\t// Check to see if this client needs to do this.\n\t\tconst clearCandidates: string[] = [];\n\t\tconst tasks: Promise<unknown>[] = [];\n\n\t\tfor (const [taskUrl] of this.locallyRunnableTasks) {\n\t\t\tif (!this.getTaskClientId(taskUrl)) {\n\t\t\t\ttasks.push(this.writeCore(taskUrl, this.clientId));\n\t\t\t}\n\t\t}\n\n\t\tfor (const taskUrl of this.consensusRegisterCollection.keys()) {\n\t\t\tconst currentClient = this.getTaskClientId(taskUrl);\n\t\t\tif (currentClient && this.runtime.getQuorum().getMember(currentClient) === undefined) {\n\t\t\t\tclearCandidates.push(taskUrl);\n\t\t\t}\n\t\t}\n\n\t\ttasks.push(this.clearTasks(clearCandidates));\n\n\t\tPromise.all(tasks).catch((error) => {\n\t\t\tthis.sendErrorEvent(\"AgentScheduler_InitError\", error);\n\t\t});\n\t}\n\n\tprivate clearRunningTasks(): void {\n\t\tconst tasks = this.runningTasks;\n\t\tthis.runningTasks = new Set<string>();\n\n\t\tif (this.isActive()) {\n\t\t\t// Clear all tasks with UnattachedClientId (if was unattached) and reapply for tasks with new clientId\n\t\t\t// If we are simply disconnected, then proper cleanup will be done on connection.\n\t\t\tthis.initializeCore();\n\t\t}\n\n\t\tfor (const task of tasks) {\n\t\t\tthis.emit(\"lost\", task);\n\t\t}\n\t}\n\n\tprivate sendErrorEvent(eventName: string, error: unknown, key?: string): void {\n\t\tthis.logger.sendErrorEvent({ eventName, key }, error);\n\t}\n}\n\nclass AgentSchedulerRuntime extends FluidDataStoreRuntime {\n\tconstructor(\n\t\tdataStoreContext: IFluidDataStoreContext,\n\t\tsharedObjectRegistry: ISharedObjectRegistry,\n\t\texisting: boolean,\n\t) {\n\t\tsuper(dataStoreContext, sharedObjectRegistry, existing, async () =>\n\t\t\tAgentScheduler.load(this, dataStoreContext, existing),\n\t\t);\n\t}\n\tpublic async request(request: IRequest): Promise<IResponse> {\n\t\tconst response = await super.request(request);\n\t\tif (response.status === 404 && (request.url === \"\" || request.url === \"/\")) {\n\t\t\tconst agentScheduler = await this.entryPoint.get();\n\t\t\tassert(\n\t\t\t\tagentScheduler !== undefined,\n\t\t\t\t0x466 /* entryPoint for AgentSchedulerRuntime should have been initialized by now */,\n\t\t\t);\n\n\t\t\treturn { status: 200, mimeType: \"fluid/object\", value: agentScheduler };\n\t\t}\n\t\treturn response;\n\t}\n}\n\n/**\n * @legacy\n * @alpha\n */\nexport class AgentSchedulerFactory implements IFluidDataStoreFactory {\n\tpublic static readonly type = \"_scheduler\";\n\tpublic readonly type = AgentSchedulerFactory.type;\n\n\tpublic get IFluidDataStoreFactory(): AgentSchedulerFactory {\n\t\treturn this;\n\t}\n\n\tpublic static get registryEntry(): NamedFluidDataStoreRegistryEntry {\n\t\treturn [this.type, Promise.resolve(new AgentSchedulerFactory())];\n\t}\n\n\tpublic static async createChildInstance(\n\t\tparentContext: IFluidDataStoreContext,\n\t): Promise<IAgentScheduler> {\n\t\tconst packagePath = [...parentContext.packagePath, AgentSchedulerFactory.type];\n\t\tconst dataStore = await parentContext.containerRuntime.createDataStore(packagePath);\n\t\tconst entryPoint: FluidObject<IAgentScheduler> = await dataStore.entryPoint.get();\n\n\t\t// AgentSchedulerRuntime always puts an AgentScheduler object in the data store's entryPoint, but double-check\n\t\t// while we plumb entryPoints correctly everywhere, so we can be sure the cast below is fine.\n\t\tassert(\n\t\t\tentryPoint.IAgentScheduler !== undefined,\n\t\t\t0x467 /* The data store's entryPoint is not an AgentScheduler! */,\n\t\t);\n\t\treturn entryPoint as unknown as AgentScheduler;\n\t}\n\n\tpublic async instantiateDataStore(\n\t\tcontext: IFluidDataStoreContext,\n\t\texisting: boolean,\n\t): Promise<FluidDataStoreRuntime> {\n\t\tconst mapFactory = SharedMap.getFactory();\n\t\tconst consensusRegisterCollectionFactory = ConsensusRegisterCollection.getFactory();\n\t\tconst dataTypes = new Map<string, IChannelFactory>();\n\t\tdataTypes.set(mapFactory.type, mapFactory);\n\t\tdataTypes.set(consensusRegisterCollectionFactory.type, consensusRegisterCollectionFactory);\n\n\t\treturn new AgentSchedulerRuntime(context, dataTypes, existing);\n\t}\n}\n"]}
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.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 { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport type {\n\tFluidObject,\n\tIFluidHandle,\n\tIFluidLoadable,\n\tIRequest,\n\tIResponse,\n} from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport {\n\tFluidDataStoreRuntime,\n\tFluidObjectHandle,\n\ttype ISharedObjectRegistry,\n} from \"@fluidframework/datastore/internal\";\nimport type {\n\tIChannelFactory,\n\tIFluidDataStoreRuntime,\n} from \"@fluidframework/datastore-definitions/internal\";\nimport { type ISharedMap, type IValueChanged, SharedMap } from \"@fluidframework/map/internal\";\nimport { ConsensusRegisterCollection } from \"@fluidframework/register-collection/internal\";\nimport type {\n\tIFluidDataStoreContext,\n\tIFluidDataStoreFactory,\n\tNamedFluidDataStoreRegistryEntry,\n} from \"@fluidframework/runtime-definitions/internal\";\nimport {\n\ttype ITelemetryLoggerExt,\n\tUsageError,\n\tcreateChildLogger,\n\ttagCodeArtifacts,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { v4 as uuid } from \"uuid\";\n\nimport type { IAgentScheduler, IAgentSchedulerEvents } from \"./agent.js\";\n\n// Note: making sure this ID is unique and does not collide with storage provided clientID\nconst UnattachedClientId = `${uuid()}_unattached`;\n\nconst mapWait = async <T = unknown>(map: ISharedMap, key: string): Promise<T> => {\n\tconst maybeValue = map.get<T>(key);\n\tif (maybeValue !== undefined) {\n\t\treturn maybeValue;\n\t}\n\n\treturn new Promise((resolve) => {\n\t\tconst handler = (changed: IValueChanged): void => {\n\t\t\tif (changed.key === key) {\n\t\t\t\tmap.off(\"valueChanged\", handler);\n\t\t\t\tconst value = map.get<T>(changed.key);\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tthrow new Error(\"Unexpected valueChanged result\");\n\t\t\t\t}\n\t\t\t\tresolve(value);\n\t\t\t}\n\t\t};\n\t\tmap.on(\"valueChanged\", handler);\n\t});\n};\n\nconst schedulerId = \"scheduler\";\n\nexport class AgentScheduler\n\textends TypedEventEmitter<IAgentSchedulerEvents>\n\timplements IAgentScheduler\n{\n\tpublic static async load(\n\t\truntime: IFluidDataStoreRuntime,\n\t\tcontext: IFluidDataStoreContext,\n\t\texisting: boolean,\n\t): Promise<IAgentScheduler> {\n\t\tlet root: ISharedMap;\n\t\tlet consensusRegisterCollection: ConsensusRegisterCollection<string | null>;\n\t\tif (existing) {\n\t\t\troot = (await runtime.getChannel(\"root\")) as ISharedMap;\n\t\t\tconst handle = await mapWait<IFluidHandle<ConsensusRegisterCollection<string | null>>>(\n\t\t\t\troot,\n\t\t\t\tschedulerId,\n\t\t\t);\n\t\t\tassert(handle !== undefined, 0x116 /* \"Missing handle on scheduler load\" */);\n\t\t\tconsensusRegisterCollection = await handle.get();\n\t\t} else {\n\t\t\troot = SharedMap.create(runtime, \"root\");\n\t\t\troot.bindToContext();\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\tconsensusRegisterCollection = ConsensusRegisterCollection.create(runtime);\n\t\t\tconsensusRegisterCollection.bindToContext();\n\t\t\troot.set(schedulerId, consensusRegisterCollection.handle);\n\t\t}\n\t\tconst agentScheduler = new AgentScheduler(runtime, context, consensusRegisterCollection);\n\t\tagentScheduler.initialize();\n\n\t\treturn agentScheduler;\n\t}\n\n\tpublic get IAgentScheduler(): IAgentScheduler {\n\t\treturn this;\n\t}\n\tpublic get IFluidLoadable(): IFluidLoadable {\n\t\treturn this;\n\t}\n\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tprivate get clientId(): string {\n\t\tif (this.runtime.attachState === AttachState.Detached) {\n\t\t\treturn UnattachedClientId;\n\t\t}\n\t\tconst clientId = this.runtime.clientId;\n\t\tassert(!!clientId, 0x117 /* \"Trying to get missing clientId!\" */);\n\t\treturn clientId;\n\t}\n\n\t// Set of tasks registered by this client.\n\t// Has no relationship with lists below.\n\t// The only requirement here - a task can be registered by a client only once.\n\t// Other clients can pick these tasks.\n\tprivate readonly registeredTasks = new Set<string>();\n\n\t// List of all tasks client is capable of running (essentially expressed desire to run)\n\t// Client will proactively attempt to pick them up these tasks if they are not assigned to other clients.\n\t// This is a strict superset of tasks running in the client.\n\tprivate readonly locallyRunnableTasks = new Map<string, () => Promise<void>>();\n\n\t// Set of registered tasks client is currently running.\n\t// It's subset of this.locallyRunnableTasks\n\tprivate runningTasks = new Set<string>();\n\n\tprivate readonly _handle: IFluidHandle<this>;\n\n\tconstructor(\n\t\tprivate readonly runtime: IFluidDataStoreRuntime,\n\t\tprivate readonly context: IFluidDataStoreContext,\n\t\tprivate readonly consensusRegisterCollection: ConsensusRegisterCollection<string | null>,\n\t) {\n\t\tsuper();\n\t\tthis.logger = createChildLogger({ logger: runtime.logger });\n\t\t// We are expecting this class to have many listeners, so we suppress noisy \"MaxListenersExceededWarning\" logging.\n\t\tsuper.setMaxListeners(0);\n\t\tthis._handle = new FluidObjectHandle(this, \"\", this.runtime.objectsRoutingContext);\n\t}\n\n\tpublic get handle(): IFluidHandle<this> {\n\t\treturn this._handle;\n\t}\n\n\tpublic async register(...taskUrls: string[]): Promise<void> {\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tif (this.registeredTasks.has(taskUrl)) {\n\t\t\t\tthrow new UsageError(`Task is already registered`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t}\n\t\tconst unregisteredTasks: string[] = [];\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tthis.registeredTasks.add(taskUrl);\n\t\t\t// Only register for a new task.\n\t\t\tconst currentClient = this.getTaskClientId(taskUrl);\n\t\t\tif (currentClient === undefined) {\n\t\t\t\tunregisteredTasks.push(taskUrl);\n\t\t\t}\n\t\t}\n\t\treturn this.registerCore(unregisteredTasks);\n\t}\n\n\tpublic async pick(taskUrl: string, worker: () => Promise<void>): Promise<void> {\n\t\tif (this.locallyRunnableTasks.has(taskUrl)) {\n\t\t\tthrow new UsageError(`Task is already attempted`, tagCodeArtifacts({ taskUrl }));\n\t\t}\n\t\tthis.locallyRunnableTasks.set(taskUrl, worker);\n\n\t\t// We have a policy to disallow non-interactive clients from taking tasks. Callers of pick() can\n\t\t// either perform this check proactively and call conditionally, or catch the error (in which case\n\t\t// they can know they will not get the task).\n\t\tassert(\n\t\t\tthis.context.deltaManager.clientDetails.capabilities.interactive,\n\t\t\t0x118 /* \"Bad client interactive check\" */,\n\t\t);\n\n\t\t// Check the current status and express interest if it's a new one (undefined) or currently unpicked (null).\n\t\tif (this.isActive()) {\n\t\t\tconst currentClient = this.getTaskClientId(taskUrl);\n\t\t\tif (currentClient === undefined || currentClient === null) {\n\t\t\t\tawait this.writeCore(taskUrl, this.clientId);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async release(...taskUrls: string[]): Promise<void> {\n\t\tconst active = this.isActive();\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tif (!this.locallyRunnableTasks.has(taskUrl)) {\n\t\t\t\tthrow new UsageError(`Task was never registered`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t\tif (!this.runningTasks.has(taskUrl)) {\n\t\t\t\t// If we got disconnected (and are attached), tasks that we WERE picked for at the time of disconnect\n\t\t\t\t// will still show us as holding the task according to getTaskClientId (the CRC is stale), but we\n\t\t\t\t// should not try to release because our disconnect will already result in either someone else or\n\t\t\t\t// ourselves clearing the task upon reconnect.\n\t\t\t\t// This UsageError is to enforce that the caller should check AgentScheduler.pickedTasks before trying\n\t\t\t\t// to release a task.\n\t\t\t\tthrow new UsageError(`Task is not currently picked`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t\t// We may only release tasks that we KNOW we hold (detached state or connected and own the CRC). If we're\n\t\t\t// attached+disconnected then we'll lose the task automatically, and so may not release manually (someone\n\t\t\t// else might hold it by the time we reconnect)\n\t\t\tassert(active, 0x119 /* \"This agent became inactive while releasing\" */);\n\t\t\tif (this.getTaskClientId(taskUrl) !== this.clientId) {\n\t\t\t\tthrow new UsageError(`Task was never picked`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t}\n\t\treturn this.releaseCore([...taskUrls]);\n\t}\n\n\tpublic pickedTasks(): string[] {\n\t\treturn [...this.runningTasks.values()];\n\t}\n\t/* eslint-disable unicorn/no-null */\n\tprivate async registerCore(taskUrls: string[]): Promise<void> {\n\t\tif (taskUrls.length > 0) {\n\t\t\tconst registersP: Promise<void>[] = [];\n\t\t\tfor (const taskUrl of taskUrls) {\n\t\t\t\tregistersP.push(this.writeCore(taskUrl, null));\n\t\t\t}\n\t\t\tawait Promise.all(registersP);\n\n\t\t\t// The registers should have up to date results now. Check the status.\n\t\t\tfor (const taskUrl of taskUrls) {\n\t\t\t\tconst taskStatus = this.getTaskClientId(taskUrl);\n\n\t\t\t\t// Task should be either registered (null) or picked up.\n\t\t\t\tassert(taskStatus !== undefined, 0x11a /* `Unsuccessful registration` */);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async releaseCore(taskUrls: string[]): Promise<void> {\n\t\tif (taskUrls.length > 0) {\n\t\t\tconst releasesP: Promise<void>[] = [];\n\t\t\tfor (const taskUrl of taskUrls) {\n\t\t\t\t// Remove from local map so that it can be picked later.\n\t\t\t\tthis.locallyRunnableTasks.delete(taskUrl);\n\t\t\t\treleasesP.push(this.writeCore(taskUrl, null));\n\t\t\t}\n\t\t\tawait Promise.all(releasesP);\n\t\t}\n\t}\n\n\tprivate async clearTasks(taskUrls: string[]): Promise<void> {\n\t\tassert(this.isActive(), 0x11b /* \"Trying to clear tasks on inactive agent\" */);\n\t\tconst clearP: Promise<void>[] = [];\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tclearP.push(this.writeCore(taskUrl, null));\n\t\t}\n\t\tawait Promise.all(clearP);\n\t}\n\n\tprivate getTaskClientId(url: string): string | null | undefined {\n\t\treturn this.consensusRegisterCollection.read(url);\n\t}\n\n\tprivate async writeCore(key: string, clientId: string | null): Promise<void> {\n\t\tawait this.consensusRegisterCollection.write(key, clientId);\n\t}\n\n\tprivate initialize(): void {\n\t\tconst quorum = this.runtime.getQuorum();\n\t\t// A client left the quorum. Iterate and clear tasks held by that client.\n\t\t// Ideally a leader should do this cleanup. But it's complicated when a leader itself leaves.\n\t\t// Probably okay for now to have every client try to do this.\n\t\t// eslint-disable-next-line @typescript-eslint/no-misused-promises\n\t\tquorum.on(\"removeMember\", async (clientId: string) => {\n\t\t\t// TODO AB#19980: The scenario with a detached routing context is not fully supported.\n\t\t\tif (!this.runtime.objectsRoutingContext.isAttached) return;\n\t\t\t// Cleanup only if connected. If not, cleanup will happen in initializeCore() that runs on connection.\n\t\t\tif (this.isActive()) {\n\t\t\t\tconst tasks: Promise<unknown>[] = [];\n\t\t\t\tconst leftTasks: string[] = [];\n\t\t\t\tfor (const taskUrl of this.consensusRegisterCollection.keys()) {\n\t\t\t\t\tif (this.getTaskClientId(taskUrl) === clientId) {\n\t\t\t\t\t\tif (this.locallyRunnableTasks.has(taskUrl)) {\n\t\t\t\t\t\t\ttasks.push(this.writeCore(taskUrl, this.clientId));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tleftTasks.push(taskUrl);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttasks.push(this.clearTasks(leftTasks));\n\t\t\t\tawait Promise.all(tasks).catch((error) => {\n\t\t\t\t\tthis.sendErrorEvent(\"AgentScheduler_RemoveMemberError\", error);\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\t// Listeners for new/released tasks. All clients will try to grab at the same time.\n\t\t// May be we want a randomized timer (Something like raft) to reduce chattiness?\n\t\tthis.consensusRegisterCollection.on(\n\t\t\t\"atomicChanged\",\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-misused-promises\n\t\t\tasync (key: string, currentClient: string | null) => {\n\t\t\t\t// Check if this client was chosen.\n\t\t\t\tif (this.isActive() && currentClient === this.clientId) {\n\t\t\t\t\tthis.onNewTaskAssigned(key);\n\t\t\t\t} else {\n\t\t\t\t\t// The call below mutates the consensusRegisterCollection in\n\t\t\t\t\t// its event handler, which is not safe.\n\t\t\t\t\t// We need to force this to be part of a different batch of ops by\n\t\t\t\t\t// scheduling a microtask in order to work around the current validations.\n\t\t\t\t\t// This is not recommended and should be avoided.\n\t\t\t\t\tawait Promise.resolve().then(async () => {\n\t\t\t\t\t\tawait this.onTaskReassigned(key, currentClient);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\tif (this.isActive()) {\n\t\t\tthis.initializeCore();\n\t\t}\n\n\t\tthis.runtime.on(\"connected\", () => {\n\t\t\tif (this.isActive()) {\n\t\t\t\tthis.initializeCore();\n\t\t\t}\n\t\t});\n\n\t\tif (this.runtime.attachState === AttachState.Detached) {\n\t\t\tthis.runtime\n\t\t\t\t.waitAttached()\n\t\t\t\t.then(() => {\n\t\t\t\t\tthis.clearRunningTasks();\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tthis.sendErrorEvent(\"AgentScheduler_clearRunningTasks\", error);\n\t\t\t\t});\n\t\t}\n\n\t\tthis.runtime.on(\"disconnected\", () => {\n\t\t\tif (this.runtime.attachState !== AttachState.Detached) {\n\t\t\t\tthis.clearRunningTasks();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate onNewTaskAssigned(key: string): void {\n\t\tassert(!this.runningTasks.has(key), 0x11d /* \"task is already running\" */);\n\t\tthis.runningTasks.add(key);\n\t\tconst worker = this.locallyRunnableTasks.get(key);\n\t\tif (worker === undefined) {\n\t\t\tthis.sendErrorEvent(\"AgentScheduler_UnwantedChange\", undefined, key);\n\t\t} else {\n\t\t\tthis.emit(\"picked\", key);\n\t\t\tworker().catch((error) => {\n\t\t\t\tthis.sendErrorEvent(\"AgentScheduler_FailedWork\", error, key);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async onTaskReassigned(key: string, currentClient: string | null): Promise<void> {\n\t\tif (this.runningTasks.has(key)) {\n\t\t\tthis.runningTasks.delete(key);\n\t\t\tthis.emit(\"released\", key);\n\t\t}\n\t\tassert(currentClient !== undefined, 0x11e /* \"client is undefined\" */);\n\t\tif (this.isActive()) {\n\t\t\t// attempt to pick up task if we are connected.\n\t\t\t// If not, initializeCore() will do it when connected\n\t\t\tif (currentClient === null) {\n\t\t\t\tif (this.locallyRunnableTasks.has(key)) {\n\t\t\t\t\tawait this.writeCore(key, this.clientId);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Check if the op came from dropped client\n\t\t\t// This could happen when \"old\" ops are submitted on reconnection.\n\t\t\t// They carry \"old\" ref seq number, but if write is not contested, it will get accepted\n\t\t\telse if (this.runtime.getQuorum().getMember(currentClient) === undefined) {\n\t\t\t\tawait this.writeCore(key, null);\n\t\t\t}\n\t\t}\n\t}\n\t/* eslint-enable unicorn/no-null */\n\n\tprivate isActive(): boolean {\n\t\t// Scheduler should be active in detached container.\n\t\tif (this.runtime.attachState === AttachState.Detached) {\n\t\t\treturn true;\n\t\t}\n\t\tif (!this.runtime.connected) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Note: we are not checking for this.context.deltaManager.clientDetails.capabilities.interactive\n\t\t// here. Instead we assert in pick() if a non-interactive client tries to pick.\n\n\t\treturn this.context.deltaManager.active;\n\t}\n\n\tprivate initializeCore(): void {\n\t\t// Nobody released the tasks held by last client in previous session.\n\t\t// Check to see if this client needs to do this.\n\t\tconst clearCandidates: string[] = [];\n\t\tconst tasks: Promise<unknown>[] = [];\n\n\t\tfor (const [taskUrl] of this.locallyRunnableTasks) {\n\t\t\tif (!this.getTaskClientId(taskUrl)) {\n\t\t\t\ttasks.push(this.writeCore(taskUrl, this.clientId));\n\t\t\t}\n\t\t}\n\n\t\tfor (const taskUrl of this.consensusRegisterCollection.keys()) {\n\t\t\tconst currentClient = this.getTaskClientId(taskUrl);\n\t\t\tif (currentClient && this.runtime.getQuorum().getMember(currentClient) === undefined) {\n\t\t\t\tclearCandidates.push(taskUrl);\n\t\t\t}\n\t\t}\n\n\t\ttasks.push(this.clearTasks(clearCandidates));\n\n\t\tPromise.all(tasks).catch((error) => {\n\t\t\tthis.sendErrorEvent(\"AgentScheduler_InitError\", error);\n\t\t});\n\t}\n\n\tprivate clearRunningTasks(): void {\n\t\tconst tasks = this.runningTasks;\n\t\tthis.runningTasks = new Set<string>();\n\n\t\tif (this.isActive()) {\n\t\t\t// Clear all tasks with UnattachedClientId (if was unattached) and reapply for tasks with new clientId\n\t\t\t// If we are simply disconnected, then proper cleanup will be done on connection.\n\t\t\tthis.initializeCore();\n\t\t}\n\n\t\tfor (const task of tasks) {\n\t\t\tthis.emit(\"lost\", task);\n\t\t}\n\t}\n\n\tprivate sendErrorEvent(eventName: string, error: unknown, key?: string): void {\n\t\tthis.logger.sendErrorEvent({ eventName, key }, error);\n\t}\n}\n\nclass AgentSchedulerRuntime extends FluidDataStoreRuntime {\n\tconstructor(\n\t\tdataStoreContext: IFluidDataStoreContext,\n\t\tsharedObjectRegistry: ISharedObjectRegistry,\n\t\texisting: boolean,\n\t) {\n\t\tsuper(dataStoreContext, sharedObjectRegistry, existing, async () =>\n\t\t\tAgentScheduler.load(this, dataStoreContext, existing),\n\t\t);\n\t}\n\tpublic async request(request: IRequest): Promise<IResponse> {\n\t\tconst response = await super.request(request);\n\t\tif (response.status === 404 && (request.url === \"\" || request.url === \"/\")) {\n\t\t\tconst agentScheduler = await this.entryPoint.get();\n\t\t\tassert(\n\t\t\t\tagentScheduler !== undefined,\n\t\t\t\t0x466 /* entryPoint for AgentSchedulerRuntime should have been initialized by now */,\n\t\t\t);\n\n\t\t\treturn { status: 200, mimeType: \"fluid/object\", value: agentScheduler };\n\t\t}\n\t\treturn response;\n\t}\n}\n\n/**\n * @legacy\n * @beta\n */\nexport class AgentSchedulerFactory implements IFluidDataStoreFactory {\n\tpublic static readonly type = \"_scheduler\";\n\tpublic readonly type = AgentSchedulerFactory.type;\n\n\tpublic get IFluidDataStoreFactory(): AgentSchedulerFactory {\n\t\treturn this;\n\t}\n\n\tpublic static get registryEntry(): NamedFluidDataStoreRegistryEntry {\n\t\treturn [this.type, Promise.resolve(new AgentSchedulerFactory())];\n\t}\n\n\tpublic static async createChildInstance(\n\t\tparentContext: IFluidDataStoreContext,\n\t): Promise<IAgentScheduler> {\n\t\tconst packagePath = [...parentContext.packagePath, AgentSchedulerFactory.type];\n\t\tconst dataStore = await parentContext.containerRuntime.createDataStore(packagePath);\n\t\tconst entryPoint: FluidObject<IAgentScheduler> = await dataStore.entryPoint.get();\n\n\t\t// AgentSchedulerRuntime always puts an AgentScheduler object in the data store's entryPoint, but double-check\n\t\t// while we plumb entryPoints correctly everywhere, so we can be sure the cast below is fine.\n\t\tassert(\n\t\t\tentryPoint.IAgentScheduler !== undefined,\n\t\t\t0x467 /* The data store's entryPoint is not an AgentScheduler! */,\n\t\t);\n\t\treturn entryPoint as unknown as AgentScheduler;\n\t}\n\n\tpublic async instantiateDataStore(\n\t\tcontext: IFluidDataStoreContext,\n\t\texisting: boolean,\n\t): Promise<FluidDataStoreRuntime> {\n\t\tconst mapFactory = SharedMap.getFactory();\n\t\tconst consensusRegisterCollectionFactory = ConsensusRegisterCollection.getFactory();\n\t\tconst dataTypes = new Map<string, IChannelFactory>();\n\t\tdataTypes.set(mapFactory.type, mapFactory);\n\t\tdataTypes.set(consensusRegisterCollectionFactory.type, consensusRegisterCollectionFactory);\n\n\t\treturn new AgentSchedulerRuntime(context, dataTypes, existing);\n\t}\n}\n"]}
@@ -8,7 +8,7 @@ import type { IAgentScheduler } from "./agent.js";
8
8
  /**
9
9
  * Events emitted by {@link TaskSubscription}.
10
10
  * @legacy
11
- * @alpha
11
+ * @beta
12
12
  */
13
13
  export interface ITaskSubscriptionEvents extends IEvent {
14
14
  (event: "gotTask" | "lostTask", listener: () => void): any;
@@ -16,7 +16,7 @@ export interface ITaskSubscriptionEvents extends IEvent {
16
16
  /**
17
17
  * TaskSubscription works with an AgentScheduler to make it easier to monitor a specific task ownership.
18
18
  * @legacy
19
- * @alpha
19
+ * @beta
20
20
  */
21
21
  export declare class TaskSubscription extends TypedEventEmitter<ITaskSubscriptionEvents> {
22
22
  private readonly agentScheduler;
@@ -9,7 +9,7 @@ const client_utils_1 = require("@fluid-internal/client-utils");
9
9
  /**
10
10
  * TaskSubscription works with an AgentScheduler to make it easier to monitor a specific task ownership.
11
11
  * @legacy
12
- * @alpha
12
+ * @beta
13
13
  */
14
14
  class TaskSubscription extends client_utils_1.TypedEventEmitter {
15
15
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"taskSubscription.js","sourceRoot":"","sources":["../src/taskSubscription.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAAiE;AAcjE;;;;GAIG;AACH,MAAa,gBAAiB,SAAQ,gCAA0C;IAG/E;;;OAGG;IACH,YACkB,cAA+B,EAChC,MAAc;QAE9B,KAAK,EAAE,CAAC;QAHS,mBAAc,GAAd,cAAc,CAAiB;QAChC,WAAM,GAAN,MAAM,CAAQ;QARvB,eAAU,GAAY,KAAK,CAAC;QAWnC,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAe,EAAE,EAAE;YAC/C,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtB,CAAC;QACF,CAAC,CAAC,CAAC;QACH,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,OAAe,EAAE,EAAE;YACjD,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvB,CAAC;QACF,CAAC,CAAC,CAAC;QACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,OAAe,EAAE,EAAE;YAC7C,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvB,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACI,QAAQ;QACd,OAAO,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChE,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACtB,uFAAuF;YACvF,gFAAgF;YAChF,0FAA0F;YAC1F,qCAAqC;YACrC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACtE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACxB,CAAC;IACF,CAAC;CACD;AAnDD,4CAmDC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IEvent } from \"@fluidframework/core-interfaces\";\n\nimport type { IAgentScheduler } from \"./agent.js\";\n\n/**\n * Events emitted by {@link TaskSubscription}.\n * @legacy\n * @alpha\n */\nexport interface ITaskSubscriptionEvents extends IEvent {\n\t(event: \"gotTask\" | \"lostTask\", listener: () => void);\n}\n\n/**\n * TaskSubscription works with an AgentScheduler to make it easier to monitor a specific task ownership.\n * @legacy\n * @alpha\n */\nexport class TaskSubscription extends TypedEventEmitter<ITaskSubscriptionEvents> {\n\tprivate subscribed: boolean = false;\n\n\t/**\n\t * @param agentScheduler - The AgentScheduler that will be subscribed against\n\t * @param taskId - The string ID of the task to subscribe against\n\t */\n\tconstructor(\n\t\tprivate readonly agentScheduler: IAgentScheduler,\n\t\tpublic readonly taskId: string,\n\t) {\n\t\tsuper();\n\t\tagentScheduler.on(\"picked\", (_taskId: string) => {\n\t\t\tif (_taskId === this.taskId) {\n\t\t\t\tthis.emit(\"gotTask\");\n\t\t\t}\n\t\t});\n\t\tagentScheduler.on(\"released\", (_taskId: string) => {\n\t\t\tif (_taskId === this.taskId) {\n\t\t\t\tthis.emit(\"lostTask\");\n\t\t\t}\n\t\t});\n\t\tagentScheduler.on(\"lost\", (_taskId: string) => {\n\t\t\tif (_taskId === this.taskId) {\n\t\t\t\tthis.emit(\"lostTask\");\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Check if currently holding ownership of the task.\n\t * @returns true if currently the task owner, false otherwise.\n\t */\n\tpublic haveTask(): boolean {\n\t\treturn this.agentScheduler.pickedTasks().includes(this.taskId);\n\t}\n\n\t/**\n\t * Volunteer for the task. By default, the TaskSubscription will only watch the task and not volunteer.\n\t * This is safe to call multiple times across multiple TaskSubscriptions.\n\t */\n\tpublic volunteer(): void {\n\t\tif (!this.subscribed) {\n\t\t\t// AgentScheduler throws if the same task is picked twice but we don't care because our\n\t\t\t// worker does nothing. We only care that the AgentScheduler is trying to pick.\n\t\t\t// We also don't care if we throw due to failing the interactive check, because then we'll\n\t\t\t// just appear to never get the task.\n\t\t\tthis.agentScheduler.pick(this.taskId, async () => {}).catch(() => {});\n\t\t\tthis.subscribed = true;\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"taskSubscription.js","sourceRoot":"","sources":["../src/taskSubscription.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAAiE;AAcjE;;;;GAIG;AACH,MAAa,gBAAiB,SAAQ,gCAA0C;IAG/E;;;OAGG;IACH,YACkB,cAA+B,EAChC,MAAc;QAE9B,KAAK,EAAE,CAAC;QAHS,mBAAc,GAAd,cAAc,CAAiB;QAChC,WAAM,GAAN,MAAM,CAAQ;QARvB,eAAU,GAAY,KAAK,CAAC;QAWnC,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAe,EAAE,EAAE;YAC/C,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtB,CAAC;QACF,CAAC,CAAC,CAAC;QACH,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,OAAe,EAAE,EAAE;YACjD,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvB,CAAC;QACF,CAAC,CAAC,CAAC;QACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,OAAe,EAAE,EAAE;YAC7C,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvB,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACI,QAAQ;QACd,OAAO,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChE,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACtB,uFAAuF;YACvF,gFAAgF;YAChF,0FAA0F;YAC1F,qCAAqC;YACrC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACtE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACxB,CAAC;IACF,CAAC;CACD;AAnDD,4CAmDC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IEvent } from \"@fluidframework/core-interfaces\";\n\nimport type { IAgentScheduler } from \"./agent.js\";\n\n/**\n * Events emitted by {@link TaskSubscription}.\n * @legacy\n * @beta\n */\nexport interface ITaskSubscriptionEvents extends IEvent {\n\t(event: \"gotTask\" | \"lostTask\", listener: () => void);\n}\n\n/**\n * TaskSubscription works with an AgentScheduler to make it easier to monitor a specific task ownership.\n * @legacy\n * @beta\n */\nexport class TaskSubscription extends TypedEventEmitter<ITaskSubscriptionEvents> {\n\tprivate subscribed: boolean = false;\n\n\t/**\n\t * @param agentScheduler - The AgentScheduler that will be subscribed against\n\t * @param taskId - The string ID of the task to subscribe against\n\t */\n\tconstructor(\n\t\tprivate readonly agentScheduler: IAgentScheduler,\n\t\tpublic readonly taskId: string,\n\t) {\n\t\tsuper();\n\t\tagentScheduler.on(\"picked\", (_taskId: string) => {\n\t\t\tif (_taskId === this.taskId) {\n\t\t\t\tthis.emit(\"gotTask\");\n\t\t\t}\n\t\t});\n\t\tagentScheduler.on(\"released\", (_taskId: string) => {\n\t\t\tif (_taskId === this.taskId) {\n\t\t\t\tthis.emit(\"lostTask\");\n\t\t\t}\n\t\t});\n\t\tagentScheduler.on(\"lost\", (_taskId: string) => {\n\t\t\tif (_taskId === this.taskId) {\n\t\t\t\tthis.emit(\"lostTask\");\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Check if currently holding ownership of the task.\n\t * @returns true if currently the task owner, false otherwise.\n\t */\n\tpublic haveTask(): boolean {\n\t\treturn this.agentScheduler.pickedTasks().includes(this.taskId);\n\t}\n\n\t/**\n\t * Volunteer for the task. By default, the TaskSubscription will only watch the task and not volunteer.\n\t * This is safe to call multiple times across multiple TaskSubscriptions.\n\t */\n\tpublic volunteer(): void {\n\t\tif (!this.subscribed) {\n\t\t\t// AgentScheduler throws if the same task is picked twice but we don't care because our\n\t\t\t// worker does nothing. We only care that the AgentScheduler is trying to pick.\n\t\t\t// We also don't care if we throw due to failing the interactive check, because then we'll\n\t\t\t// just appear to never get the task.\n\t\t\tthis.agentScheduler.pick(this.taskId, async () => {}).catch(() => {});\n\t\t\tthis.subscribed = true;\n\t\t}\n\t}\n}\n"]}
package/lib/agent.d.ts CHANGED
@@ -5,12 +5,12 @@
5
5
  import type { IEvent, IEventProvider, IFluidLoadable } from "@fluidframework/core-interfaces";
6
6
  /**
7
7
  * @legacy
8
- * @alpha
8
+ * @beta
9
9
  */
10
10
  export declare const IAgentScheduler: keyof IProvideAgentScheduler;
11
11
  /**
12
12
  * @legacy
13
- * @alpha
13
+ * @beta
14
14
  */
15
15
  export interface IProvideAgentScheduler {
16
16
  readonly IAgentScheduler: IAgentScheduler;
@@ -18,7 +18,7 @@ export interface IProvideAgentScheduler {
18
18
  /**
19
19
  * Events emitted by {@link (IAgentScheduler:interface)}.
20
20
  * @legacy
21
- * @alpha
21
+ * @beta
22
22
  */
23
23
  export interface IAgentSchedulerEvents extends IEvent {
24
24
  /**
@@ -43,7 +43,7 @@ export interface IAgentSchedulerEvents extends IEvent {
43
43
  /**
44
44
  * Agent scheduler distributes a set of tasks/variables across connected clients.
45
45
  * @legacy
46
- * @alpha
46
+ * @beta
47
47
  */
48
48
  export interface IAgentScheduler extends IProvideAgentScheduler, IEventProvider<IAgentSchedulerEvents>, IFluidLoadable {
49
49
  /**
package/lib/agent.js CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
  /**
6
6
  * @legacy
7
- * @alpha
7
+ * @beta
8
8
  */
9
9
  export const IAgentScheduler = "IAgentScheduler";
10
10
  //# sourceMappingURL=agent.js.map
package/lib/agent.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAiC,iBAAiB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IEvent, IEventProvider, IFluidLoadable } from \"@fluidframework/core-interfaces\";\n\n/**\n * @legacy\n * @alpha\n */\nexport const IAgentScheduler: keyof IProvideAgentScheduler = \"IAgentScheduler\";\n\n/**\n * @legacy\n * @alpha\n */\nexport interface IProvideAgentScheduler {\n\treadonly IAgentScheduler: IAgentScheduler;\n}\n\n/**\n * Events emitted by {@link (IAgentScheduler:interface)}.\n * @legacy\n * @alpha\n */\nexport interface IAgentSchedulerEvents extends IEvent {\n\t/**\n\t * Event when ownership of task changes\n\t * @param event - name of the event:\n\t *\n\t * - \"picked\" - the task has been assigned to this client, in response to pick() being called\n\t * If client loses this task (due to disconnect), it will attempt to pick it again (on connection)\n\t * automatically, unless release() is called\n\t *\n\t * - \"released\" - the task was successfully released back to the pool. Client will not attempt to\n\t * re-acquire the task, unless pick() is called.\n\t *\n\t * - \"lost\" - task is lost due to disconnect or data store / container being attached.\n\t * Task will be picked up again by some connected client (this client will try as well,\n\t * unless release() is called)\n\t *\n\t * @param listener - callback notified when change happened for particular key\n\t */\n\t(event: \"picked\" | \"released\" | \"lost\", listener: (taskId: string) => void);\n}\n\n/**\n * Agent scheduler distributes a set of tasks/variables across connected clients.\n * @legacy\n * @alpha\n */\nexport interface IAgentScheduler\n\textends IProvideAgentScheduler,\n\t\tIEventProvider<IAgentSchedulerEvents>,\n\t\tIFluidLoadable {\n\t/**\n\t * Registers a set of new tasks to distribute amongst connected clients. Only use this if a client wants\n\t * a new agent to run but does not have the capability to run the agent inside the host.\n\t * Client can call pick() later if the capability changes.\n\t *\n\t * This method should only be called once per task. Duplicate calls will be rejected.\n\t */\n\tregister(...taskUrls: string[]): Promise<void>;\n\n\t/**\n\t * Attempts to pick a set of tasks. A client will only run the task if it's chosen based on consensus.\n\t * Resolves when the tasks are assigned to one of the connected clients.\n\t *\n\t * This method should only be called once per task. Duplicate calls will be rejected.\n\t *\n\t * @param worker - callback to run when task is picked up.\n\t */\n\tpick(taskId: string, worker: () => Promise<void>): Promise<void>;\n\n\t/**\n\t * Releases a set of tasks for other clients to grab. Resolves when the tasks are released.\n\t *\n\t * Only previously picked tasks are allowed. Releasing non picked tasks will get a rejection.\n\t * App can call pickedTasks() to get the picked list first.\n\t */\n\trelease(...taskUrls: string[]): Promise<void>;\n\n\t/**\n\t * Returns a list of all tasks running on this client\n\t */\n\tpickedTasks(): string[];\n}\n"]}
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAiC,iBAAiB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IEvent, IEventProvider, IFluidLoadable } from \"@fluidframework/core-interfaces\";\n\n/**\n * @legacy\n * @beta\n */\nexport const IAgentScheduler: keyof IProvideAgentScheduler = \"IAgentScheduler\";\n\n/**\n * @legacy\n * @beta\n */\nexport interface IProvideAgentScheduler {\n\treadonly IAgentScheduler: IAgentScheduler;\n}\n\n/**\n * Events emitted by {@link (IAgentScheduler:interface)}.\n * @legacy\n * @beta\n */\nexport interface IAgentSchedulerEvents extends IEvent {\n\t/**\n\t * Event when ownership of task changes\n\t * @param event - name of the event:\n\t *\n\t * - \"picked\" - the task has been assigned to this client, in response to pick() being called\n\t * If client loses this task (due to disconnect), it will attempt to pick it again (on connection)\n\t * automatically, unless release() is called\n\t *\n\t * - \"released\" - the task was successfully released back to the pool. Client will not attempt to\n\t * re-acquire the task, unless pick() is called.\n\t *\n\t * - \"lost\" - task is lost due to disconnect or data store / container being attached.\n\t * Task will be picked up again by some connected client (this client will try as well,\n\t * unless release() is called)\n\t *\n\t * @param listener - callback notified when change happened for particular key\n\t */\n\t(event: \"picked\" | \"released\" | \"lost\", listener: (taskId: string) => void);\n}\n\n/**\n * Agent scheduler distributes a set of tasks/variables across connected clients.\n * @legacy\n * @beta\n */\nexport interface IAgentScheduler\n\textends IProvideAgentScheduler,\n\t\tIEventProvider<IAgentSchedulerEvents>,\n\t\tIFluidLoadable {\n\t/**\n\t * Registers a set of new tasks to distribute amongst connected clients. Only use this if a client wants\n\t * a new agent to run but does not have the capability to run the agent inside the host.\n\t * Client can call pick() later if the capability changes.\n\t *\n\t * This method should only be called once per task. Duplicate calls will be rejected.\n\t */\n\tregister(...taskUrls: string[]): Promise<void>;\n\n\t/**\n\t * Attempts to pick a set of tasks. A client will only run the task if it's chosen based on consensus.\n\t * Resolves when the tasks are assigned to one of the connected clients.\n\t *\n\t * This method should only be called once per task. Duplicate calls will be rejected.\n\t *\n\t * @param worker - callback to run when task is picked up.\n\t */\n\tpick(taskId: string, worker: () => Promise<void>): Promise<void>;\n\n\t/**\n\t * Releases a set of tasks for other clients to grab. Resolves when the tasks are released.\n\t *\n\t * Only previously picked tasks are allowed. Releasing non picked tasks will get a rejection.\n\t * App can call pickedTasks() to get the picked list first.\n\t */\n\trelease(...taskUrls: string[]): Promise<void>;\n\n\t/**\n\t * Returns a list of all tasks running on this client\n\t */\n\tpickedTasks(): string[];\n}\n"]}
@@ -43,7 +43,7 @@ export declare class AgentScheduler extends TypedEventEmitter<IAgentSchedulerEve
43
43
  }
44
44
  /**
45
45
  * @legacy
46
- * @alpha
46
+ * @beta
47
47
  */
48
48
  export declare class AgentSchedulerFactory implements IFluidDataStoreFactory {
49
49
  static readonly type = "_scheduler";
package/lib/scheduler.js CHANGED
@@ -372,7 +372,7 @@ class AgentSchedulerRuntime extends FluidDataStoreRuntime {
372
372
  }
373
373
  /**
374
374
  * @legacy
375
- * @alpha
375
+ * @beta
376
376
  */
377
377
  export class AgentSchedulerFactory {
378
378
  constructor() {
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.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 { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport type {\n\tFluidObject,\n\tIFluidHandle,\n\tIFluidLoadable,\n\tIRequest,\n\tIResponse,\n} from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport {\n\tFluidDataStoreRuntime,\n\tFluidObjectHandle,\n\ttype ISharedObjectRegistry,\n} from \"@fluidframework/datastore/internal\";\nimport type {\n\tIChannelFactory,\n\tIFluidDataStoreRuntime,\n} from \"@fluidframework/datastore-definitions/internal\";\nimport { type ISharedMap, type IValueChanged, SharedMap } from \"@fluidframework/map/internal\";\nimport { ConsensusRegisterCollection } from \"@fluidframework/register-collection/internal\";\nimport type {\n\tIFluidDataStoreContext,\n\tIFluidDataStoreFactory,\n\tNamedFluidDataStoreRegistryEntry,\n} from \"@fluidframework/runtime-definitions/internal\";\nimport {\n\ttype ITelemetryLoggerExt,\n\tUsageError,\n\tcreateChildLogger,\n\ttagCodeArtifacts,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { v4 as uuid } from \"uuid\";\n\nimport type { IAgentScheduler, IAgentSchedulerEvents } from \"./agent.js\";\n\n// Note: making sure this ID is unique and does not collide with storage provided clientID\nconst UnattachedClientId = `${uuid()}_unattached`;\n\nconst mapWait = async <T = unknown>(map: ISharedMap, key: string): Promise<T> => {\n\tconst maybeValue = map.get<T>(key);\n\tif (maybeValue !== undefined) {\n\t\treturn maybeValue;\n\t}\n\n\treturn new Promise((resolve) => {\n\t\tconst handler = (changed: IValueChanged): void => {\n\t\t\tif (changed.key === key) {\n\t\t\t\tmap.off(\"valueChanged\", handler);\n\t\t\t\tconst value = map.get<T>(changed.key);\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tthrow new Error(\"Unexpected valueChanged result\");\n\t\t\t\t}\n\t\t\t\tresolve(value);\n\t\t\t}\n\t\t};\n\t\tmap.on(\"valueChanged\", handler);\n\t});\n};\n\nconst schedulerId = \"scheduler\";\n\nexport class AgentScheduler\n\textends TypedEventEmitter<IAgentSchedulerEvents>\n\timplements IAgentScheduler\n{\n\tpublic static async load(\n\t\truntime: IFluidDataStoreRuntime,\n\t\tcontext: IFluidDataStoreContext,\n\t\texisting: boolean,\n\t): Promise<IAgentScheduler> {\n\t\tlet root: ISharedMap;\n\t\tlet consensusRegisterCollection: ConsensusRegisterCollection<string | null>;\n\t\tif (existing) {\n\t\t\troot = (await runtime.getChannel(\"root\")) as ISharedMap;\n\t\t\tconst handle = await mapWait<IFluidHandle<ConsensusRegisterCollection<string | null>>>(\n\t\t\t\troot,\n\t\t\t\tschedulerId,\n\t\t\t);\n\t\t\tassert(handle !== undefined, 0x116 /* \"Missing handle on scheduler load\" */);\n\t\t\tconsensusRegisterCollection = await handle.get();\n\t\t} else {\n\t\t\troot = SharedMap.create(runtime, \"root\");\n\t\t\troot.bindToContext();\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\tconsensusRegisterCollection = ConsensusRegisterCollection.create(runtime);\n\t\t\tconsensusRegisterCollection.bindToContext();\n\t\t\troot.set(schedulerId, consensusRegisterCollection.handle);\n\t\t}\n\t\tconst agentScheduler = new AgentScheduler(runtime, context, consensusRegisterCollection);\n\t\tagentScheduler.initialize();\n\n\t\treturn agentScheduler;\n\t}\n\n\tpublic get IAgentScheduler(): IAgentScheduler {\n\t\treturn this;\n\t}\n\tpublic get IFluidLoadable(): IFluidLoadable {\n\t\treturn this;\n\t}\n\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tprivate get clientId(): string {\n\t\tif (this.runtime.attachState === AttachState.Detached) {\n\t\t\treturn UnattachedClientId;\n\t\t}\n\t\tconst clientId = this.runtime.clientId;\n\t\tassert(!!clientId, 0x117 /* \"Trying to get missing clientId!\" */);\n\t\treturn clientId;\n\t}\n\n\t// Set of tasks registered by this client.\n\t// Has no relationship with lists below.\n\t// The only requirement here - a task can be registered by a client only once.\n\t// Other clients can pick these tasks.\n\tprivate readonly registeredTasks = new Set<string>();\n\n\t// List of all tasks client is capable of running (essentially expressed desire to run)\n\t// Client will proactively attempt to pick them up these tasks if they are not assigned to other clients.\n\t// This is a strict superset of tasks running in the client.\n\tprivate readonly locallyRunnableTasks = new Map<string, () => Promise<void>>();\n\n\t// Set of registered tasks client is currently running.\n\t// It's subset of this.locallyRunnableTasks\n\tprivate runningTasks = new Set<string>();\n\n\tprivate readonly _handle: IFluidHandle<this>;\n\n\tconstructor(\n\t\tprivate readonly runtime: IFluidDataStoreRuntime,\n\t\tprivate readonly context: IFluidDataStoreContext,\n\t\tprivate readonly consensusRegisterCollection: ConsensusRegisterCollection<string | null>,\n\t) {\n\t\tsuper();\n\t\tthis.logger = createChildLogger({ logger: runtime.logger });\n\t\t// We are expecting this class to have many listeners, so we suppress noisy \"MaxListenersExceededWarning\" logging.\n\t\tsuper.setMaxListeners(0);\n\t\tthis._handle = new FluidObjectHandle(this, \"\", this.runtime.objectsRoutingContext);\n\t}\n\n\tpublic get handle(): IFluidHandle<this> {\n\t\treturn this._handle;\n\t}\n\n\tpublic async register(...taskUrls: string[]): Promise<void> {\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tif (this.registeredTasks.has(taskUrl)) {\n\t\t\t\tthrow new UsageError(`Task is already registered`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t}\n\t\tconst unregisteredTasks: string[] = [];\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tthis.registeredTasks.add(taskUrl);\n\t\t\t// Only register for a new task.\n\t\t\tconst currentClient = this.getTaskClientId(taskUrl);\n\t\t\tif (currentClient === undefined) {\n\t\t\t\tunregisteredTasks.push(taskUrl);\n\t\t\t}\n\t\t}\n\t\treturn this.registerCore(unregisteredTasks);\n\t}\n\n\tpublic async pick(taskUrl: string, worker: () => Promise<void>): Promise<void> {\n\t\tif (this.locallyRunnableTasks.has(taskUrl)) {\n\t\t\tthrow new UsageError(`Task is already attempted`, tagCodeArtifacts({ taskUrl }));\n\t\t}\n\t\tthis.locallyRunnableTasks.set(taskUrl, worker);\n\n\t\t// We have a policy to disallow non-interactive clients from taking tasks. Callers of pick() can\n\t\t// either perform this check proactively and call conditionally, or catch the error (in which case\n\t\t// they can know they will not get the task).\n\t\tassert(\n\t\t\tthis.context.deltaManager.clientDetails.capabilities.interactive,\n\t\t\t0x118 /* \"Bad client interactive check\" */,\n\t\t);\n\n\t\t// Check the current status and express interest if it's a new one (undefined) or currently unpicked (null).\n\t\tif (this.isActive()) {\n\t\t\tconst currentClient = this.getTaskClientId(taskUrl);\n\t\t\tif (currentClient === undefined || currentClient === null) {\n\t\t\t\tawait this.writeCore(taskUrl, this.clientId);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async release(...taskUrls: string[]): Promise<void> {\n\t\tconst active = this.isActive();\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tif (!this.locallyRunnableTasks.has(taskUrl)) {\n\t\t\t\tthrow new UsageError(`Task was never registered`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t\tif (!this.runningTasks.has(taskUrl)) {\n\t\t\t\t// If we got disconnected (and are attached), tasks that we WERE picked for at the time of disconnect\n\t\t\t\t// will still show us as holding the task according to getTaskClientId (the CRC is stale), but we\n\t\t\t\t// should not try to release because our disconnect will already result in either someone else or\n\t\t\t\t// ourselves clearing the task upon reconnect.\n\t\t\t\t// This UsageError is to enforce that the caller should check AgentScheduler.pickedTasks before trying\n\t\t\t\t// to release a task.\n\t\t\t\tthrow new UsageError(`Task is not currently picked`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t\t// We may only release tasks that we KNOW we hold (detached state or connected and own the CRC). If we're\n\t\t\t// attached+disconnected then we'll lose the task automatically, and so may not release manually (someone\n\t\t\t// else might hold it by the time we reconnect)\n\t\t\tassert(active, 0x119 /* \"This agent became inactive while releasing\" */);\n\t\t\tif (this.getTaskClientId(taskUrl) !== this.clientId) {\n\t\t\t\tthrow new UsageError(`Task was never picked`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t}\n\t\treturn this.releaseCore([...taskUrls]);\n\t}\n\n\tpublic pickedTasks(): string[] {\n\t\treturn [...this.runningTasks.values()];\n\t}\n\t/* eslint-disable unicorn/no-null */\n\tprivate async registerCore(taskUrls: string[]): Promise<void> {\n\t\tif (taskUrls.length > 0) {\n\t\t\tconst registersP: Promise<void>[] = [];\n\t\t\tfor (const taskUrl of taskUrls) {\n\t\t\t\tregistersP.push(this.writeCore(taskUrl, null));\n\t\t\t}\n\t\t\tawait Promise.all(registersP);\n\n\t\t\t// The registers should have up to date results now. Check the status.\n\t\t\tfor (const taskUrl of taskUrls) {\n\t\t\t\tconst taskStatus = this.getTaskClientId(taskUrl);\n\n\t\t\t\t// Task should be either registered (null) or picked up.\n\t\t\t\tassert(taskStatus !== undefined, 0x11a /* `Unsuccessful registration` */);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async releaseCore(taskUrls: string[]): Promise<void> {\n\t\tif (taskUrls.length > 0) {\n\t\t\tconst releasesP: Promise<void>[] = [];\n\t\t\tfor (const taskUrl of taskUrls) {\n\t\t\t\t// Remove from local map so that it can be picked later.\n\t\t\t\tthis.locallyRunnableTasks.delete(taskUrl);\n\t\t\t\treleasesP.push(this.writeCore(taskUrl, null));\n\t\t\t}\n\t\t\tawait Promise.all(releasesP);\n\t\t}\n\t}\n\n\tprivate async clearTasks(taskUrls: string[]): Promise<void> {\n\t\tassert(this.isActive(), 0x11b /* \"Trying to clear tasks on inactive agent\" */);\n\t\tconst clearP: Promise<void>[] = [];\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tclearP.push(this.writeCore(taskUrl, null));\n\t\t}\n\t\tawait Promise.all(clearP);\n\t}\n\n\tprivate getTaskClientId(url: string): string | null | undefined {\n\t\treturn this.consensusRegisterCollection.read(url);\n\t}\n\n\tprivate async writeCore(key: string, clientId: string | null): Promise<void> {\n\t\tawait this.consensusRegisterCollection.write(key, clientId);\n\t}\n\n\tprivate initialize(): void {\n\t\tconst quorum = this.runtime.getQuorum();\n\t\t// A client left the quorum. Iterate and clear tasks held by that client.\n\t\t// Ideally a leader should do this cleanup. But it's complicated when a leader itself leaves.\n\t\t// Probably okay for now to have every client try to do this.\n\t\t// eslint-disable-next-line @typescript-eslint/no-misused-promises\n\t\tquorum.on(\"removeMember\", async (clientId: string) => {\n\t\t\t// TODO AB#19980: The scenario with a detached routing context is not fully supported.\n\t\t\tif (!this.runtime.objectsRoutingContext.isAttached) return;\n\t\t\t// Cleanup only if connected. If not, cleanup will happen in initializeCore() that runs on connection.\n\t\t\tif (this.isActive()) {\n\t\t\t\tconst tasks: Promise<unknown>[] = [];\n\t\t\t\tconst leftTasks: string[] = [];\n\t\t\t\tfor (const taskUrl of this.consensusRegisterCollection.keys()) {\n\t\t\t\t\tif (this.getTaskClientId(taskUrl) === clientId) {\n\t\t\t\t\t\tif (this.locallyRunnableTasks.has(taskUrl)) {\n\t\t\t\t\t\t\ttasks.push(this.writeCore(taskUrl, this.clientId));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tleftTasks.push(taskUrl);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttasks.push(this.clearTasks(leftTasks));\n\t\t\t\tawait Promise.all(tasks).catch((error) => {\n\t\t\t\t\tthis.sendErrorEvent(\"AgentScheduler_RemoveMemberError\", error);\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\t// Listeners for new/released tasks. All clients will try to grab at the same time.\n\t\t// May be we want a randomized timer (Something like raft) to reduce chattiness?\n\t\tthis.consensusRegisterCollection.on(\n\t\t\t\"atomicChanged\",\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-misused-promises\n\t\t\tasync (key: string, currentClient: string | null) => {\n\t\t\t\t// Check if this client was chosen.\n\t\t\t\tif (this.isActive() && currentClient === this.clientId) {\n\t\t\t\t\tthis.onNewTaskAssigned(key);\n\t\t\t\t} else {\n\t\t\t\t\t// The call below mutates the consensusRegisterCollection in\n\t\t\t\t\t// its event handler, which is not safe.\n\t\t\t\t\t// We need to force this to be part of a different batch of ops by\n\t\t\t\t\t// scheduling a microtask in order to work around the current validations.\n\t\t\t\t\t// This is not recommended and should be avoided.\n\t\t\t\t\tawait Promise.resolve().then(async () => {\n\t\t\t\t\t\tawait this.onTaskReassigned(key, currentClient);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\tif (this.isActive()) {\n\t\t\tthis.initializeCore();\n\t\t}\n\n\t\tthis.runtime.on(\"connected\", () => {\n\t\t\tif (this.isActive()) {\n\t\t\t\tthis.initializeCore();\n\t\t\t}\n\t\t});\n\n\t\tif (this.runtime.attachState === AttachState.Detached) {\n\t\t\tthis.runtime\n\t\t\t\t.waitAttached()\n\t\t\t\t.then(() => {\n\t\t\t\t\tthis.clearRunningTasks();\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tthis.sendErrorEvent(\"AgentScheduler_clearRunningTasks\", error);\n\t\t\t\t});\n\t\t}\n\n\t\tthis.runtime.on(\"disconnected\", () => {\n\t\t\tif (this.runtime.attachState !== AttachState.Detached) {\n\t\t\t\tthis.clearRunningTasks();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate onNewTaskAssigned(key: string): void {\n\t\tassert(!this.runningTasks.has(key), 0x11d /* \"task is already running\" */);\n\t\tthis.runningTasks.add(key);\n\t\tconst worker = this.locallyRunnableTasks.get(key);\n\t\tif (worker === undefined) {\n\t\t\tthis.sendErrorEvent(\"AgentScheduler_UnwantedChange\", undefined, key);\n\t\t} else {\n\t\t\tthis.emit(\"picked\", key);\n\t\t\tworker().catch((error) => {\n\t\t\t\tthis.sendErrorEvent(\"AgentScheduler_FailedWork\", error, key);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async onTaskReassigned(key: string, currentClient: string | null): Promise<void> {\n\t\tif (this.runningTasks.has(key)) {\n\t\t\tthis.runningTasks.delete(key);\n\t\t\tthis.emit(\"released\", key);\n\t\t}\n\t\tassert(currentClient !== undefined, 0x11e /* \"client is undefined\" */);\n\t\tif (this.isActive()) {\n\t\t\t// attempt to pick up task if we are connected.\n\t\t\t// If not, initializeCore() will do it when connected\n\t\t\tif (currentClient === null) {\n\t\t\t\tif (this.locallyRunnableTasks.has(key)) {\n\t\t\t\t\tawait this.writeCore(key, this.clientId);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Check if the op came from dropped client\n\t\t\t// This could happen when \"old\" ops are submitted on reconnection.\n\t\t\t// They carry \"old\" ref seq number, but if write is not contested, it will get accepted\n\t\t\telse if (this.runtime.getQuorum().getMember(currentClient) === undefined) {\n\t\t\t\tawait this.writeCore(key, null);\n\t\t\t}\n\t\t}\n\t}\n\t/* eslint-enable unicorn/no-null */\n\n\tprivate isActive(): boolean {\n\t\t// Scheduler should be active in detached container.\n\t\tif (this.runtime.attachState === AttachState.Detached) {\n\t\t\treturn true;\n\t\t}\n\t\tif (!this.runtime.connected) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Note: we are not checking for this.context.deltaManager.clientDetails.capabilities.interactive\n\t\t// here. Instead we assert in pick() if a non-interactive client tries to pick.\n\n\t\treturn this.context.deltaManager.active;\n\t}\n\n\tprivate initializeCore(): void {\n\t\t// Nobody released the tasks held by last client in previous session.\n\t\t// Check to see if this client needs to do this.\n\t\tconst clearCandidates: string[] = [];\n\t\tconst tasks: Promise<unknown>[] = [];\n\n\t\tfor (const [taskUrl] of this.locallyRunnableTasks) {\n\t\t\tif (!this.getTaskClientId(taskUrl)) {\n\t\t\t\ttasks.push(this.writeCore(taskUrl, this.clientId));\n\t\t\t}\n\t\t}\n\n\t\tfor (const taskUrl of this.consensusRegisterCollection.keys()) {\n\t\t\tconst currentClient = this.getTaskClientId(taskUrl);\n\t\t\tif (currentClient && this.runtime.getQuorum().getMember(currentClient) === undefined) {\n\t\t\t\tclearCandidates.push(taskUrl);\n\t\t\t}\n\t\t}\n\n\t\ttasks.push(this.clearTasks(clearCandidates));\n\n\t\tPromise.all(tasks).catch((error) => {\n\t\t\tthis.sendErrorEvent(\"AgentScheduler_InitError\", error);\n\t\t});\n\t}\n\n\tprivate clearRunningTasks(): void {\n\t\tconst tasks = this.runningTasks;\n\t\tthis.runningTasks = new Set<string>();\n\n\t\tif (this.isActive()) {\n\t\t\t// Clear all tasks with UnattachedClientId (if was unattached) and reapply for tasks with new clientId\n\t\t\t// If we are simply disconnected, then proper cleanup will be done on connection.\n\t\t\tthis.initializeCore();\n\t\t}\n\n\t\tfor (const task of tasks) {\n\t\t\tthis.emit(\"lost\", task);\n\t\t}\n\t}\n\n\tprivate sendErrorEvent(eventName: string, error: unknown, key?: string): void {\n\t\tthis.logger.sendErrorEvent({ eventName, key }, error);\n\t}\n}\n\nclass AgentSchedulerRuntime extends FluidDataStoreRuntime {\n\tconstructor(\n\t\tdataStoreContext: IFluidDataStoreContext,\n\t\tsharedObjectRegistry: ISharedObjectRegistry,\n\t\texisting: boolean,\n\t) {\n\t\tsuper(dataStoreContext, sharedObjectRegistry, existing, async () =>\n\t\t\tAgentScheduler.load(this, dataStoreContext, existing),\n\t\t);\n\t}\n\tpublic async request(request: IRequest): Promise<IResponse> {\n\t\tconst response = await super.request(request);\n\t\tif (response.status === 404 && (request.url === \"\" || request.url === \"/\")) {\n\t\t\tconst agentScheduler = await this.entryPoint.get();\n\t\t\tassert(\n\t\t\t\tagentScheduler !== undefined,\n\t\t\t\t0x466 /* entryPoint for AgentSchedulerRuntime should have been initialized by now */,\n\t\t\t);\n\n\t\t\treturn { status: 200, mimeType: \"fluid/object\", value: agentScheduler };\n\t\t}\n\t\treturn response;\n\t}\n}\n\n/**\n * @legacy\n * @alpha\n */\nexport class AgentSchedulerFactory implements IFluidDataStoreFactory {\n\tpublic static readonly type = \"_scheduler\";\n\tpublic readonly type = AgentSchedulerFactory.type;\n\n\tpublic get IFluidDataStoreFactory(): AgentSchedulerFactory {\n\t\treturn this;\n\t}\n\n\tpublic static get registryEntry(): NamedFluidDataStoreRegistryEntry {\n\t\treturn [this.type, Promise.resolve(new AgentSchedulerFactory())];\n\t}\n\n\tpublic static async createChildInstance(\n\t\tparentContext: IFluidDataStoreContext,\n\t): Promise<IAgentScheduler> {\n\t\tconst packagePath = [...parentContext.packagePath, AgentSchedulerFactory.type];\n\t\tconst dataStore = await parentContext.containerRuntime.createDataStore(packagePath);\n\t\tconst entryPoint: FluidObject<IAgentScheduler> = await dataStore.entryPoint.get();\n\n\t\t// AgentSchedulerRuntime always puts an AgentScheduler object in the data store's entryPoint, but double-check\n\t\t// while we plumb entryPoints correctly everywhere, so we can be sure the cast below is fine.\n\t\tassert(\n\t\t\tentryPoint.IAgentScheduler !== undefined,\n\t\t\t0x467 /* The data store's entryPoint is not an AgentScheduler! */,\n\t\t);\n\t\treturn entryPoint as unknown as AgentScheduler;\n\t}\n\n\tpublic async instantiateDataStore(\n\t\tcontext: IFluidDataStoreContext,\n\t\texisting: boolean,\n\t): Promise<FluidDataStoreRuntime> {\n\t\tconst mapFactory = SharedMap.getFactory();\n\t\tconst consensusRegisterCollectionFactory = ConsensusRegisterCollection.getFactory();\n\t\tconst dataTypes = new Map<string, IChannelFactory>();\n\t\tdataTypes.set(mapFactory.type, mapFactory);\n\t\tdataTypes.set(consensusRegisterCollectionFactory.type, consensusRegisterCollectionFactory);\n\n\t\treturn new AgentSchedulerRuntime(context, dataTypes, existing);\n\t}\n}\n"]}
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AAQpE,OAAO,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAC7D,OAAO,EACN,qBAAqB,EACrB,iBAAiB,GAEjB,MAAM,oCAAoC,CAAC;AAK5C,OAAO,EAAuC,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9F,OAAO,EAAE,2BAA2B,EAAE,MAAM,8CAA8C,CAAC;AAM3F,OAAO,EAEN,UAAU,EACV,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC;AAIlC,0FAA0F;AAC1F,MAAM,kBAAkB,GAAG,GAAG,IAAI,EAAE,aAAa,CAAC;AAElD,MAAM,OAAO,GAAG,KAAK,EAAe,GAAe,EAAE,GAAW,EAAc,EAAE;IAC/E,MAAM,UAAU,GAAG,GAAG,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;IACnC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,UAAU,CAAC;IACnB,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9B,MAAM,OAAO,GAAG,CAAC,OAAsB,EAAQ,EAAE;YAChD,IAAI,OAAO,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;gBACzB,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;gBACjC,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAI,OAAO,CAAC,GAAG,CAAC,CAAC;gBACtC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBACzB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;gBACnD,CAAC;gBACD,OAAO,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;QACF,CAAC,CAAC;QACF,GAAG,CAAC,EAAE,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,WAAW,CAAC;AAEhC,MAAM,OAAO,cACZ,SAAQ,iBAAwC;IAGzC,MAAM,CAAC,KAAK,CAAC,IAAI,CACvB,OAA+B,EAC/B,OAA+B,EAC/B,QAAiB;QAEjB,IAAI,IAAgB,CAAC;QACrB,IAAI,2BAAuE,CAAC;QAC5E,IAAI,QAAQ,EAAE,CAAC;YACd,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAe,CAAC;YACxD,MAAM,MAAM,GAAG,MAAM,OAAO,CAC3B,IAAI,EACJ,WAAW,CACX,CAAC;YACF,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC7E,2BAA2B,GAAG,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC;QAClD,CAAC;aAAM,CAAC;YACP,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACzC,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,mEAAmE;YACnE,2BAA2B,GAAG,2BAA2B,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC1E,2BAA2B,CAAC,aAAa,EAAE,CAAC;YAC5C,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,2BAA2B,CAAC,MAAM,CAAC,CAAC;QAC3D,CAAC;QACD,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,2BAA2B,CAAC,CAAC;QACzF,cAAc,CAAC,UAAU,EAAE,CAAC;QAE5B,OAAO,cAAc,CAAC;IACvB,CAAC;IAED,IAAW,eAAe;QACzB,OAAO,IAAI,CAAC;IACb,CAAC;IACD,IAAW,cAAc;QACxB,OAAO,IAAI,CAAC;IACb,CAAC;IAID,IAAY,QAAQ;QACnB,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,KAAK,WAAW,CAAC,QAAQ,EAAE,CAAC;YACvD,OAAO,kBAAkB,CAAC;QAC3B,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;QACvC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAClE,OAAO,QAAQ,CAAC;IACjB,CAAC;IAmBD,YACkB,OAA+B,EAC/B,OAA+B,EAC/B,2BAAuE;QAExF,KAAK,EAAE,CAAC;QAJS,YAAO,GAAP,OAAO,CAAwB;QAC/B,YAAO,GAAP,OAAO,CAAwB;QAC/B,gCAA2B,GAA3B,2BAA2B,CAA4C;QApBzF,0CAA0C;QAC1C,wCAAwC;QACxC,8EAA8E;QAC9E,sCAAsC;QACrB,oBAAe,GAAG,IAAI,GAAG,EAAU,CAAC;QAErD,uFAAuF;QACvF,yGAAyG;QACzG,4DAA4D;QAC3C,yBAAoB,GAAG,IAAI,GAAG,EAA+B,CAAC;QAE/E,uDAAuD;QACvD,2CAA2C;QACnC,iBAAY,GAAG,IAAI,GAAG,EAAU,CAAC;QAUxC,IAAI,CAAC,MAAM,GAAG,iBAAiB,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5D,kHAAkH;QAClH,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,IAAI,iBAAiB,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACpF,CAAC;IAED,IAAW,MAAM;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAEM,KAAK,CAAC,QAAQ,CAAC,GAAG,QAAkB;QAC1C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAChC,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACvC,MAAM,IAAI,UAAU,CAAC,4BAA4B,EAAE,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YACnF,CAAC;QACF,CAAC;QACD,MAAM,iBAAiB,GAAa,EAAE,CAAC;QACvC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAClC,gCAAgC;YAChC,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACpD,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;gBACjC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACjC,CAAC;QACF,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC;IAC7C,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,OAAe,EAAE,MAA2B;QAC7D,IAAI,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,UAAU,CAAC,2BAA2B,EAAE,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAE/C,iGAAiG;QACjG,kGAAkG;QAClG,6CAA6C;QAC7C,MAAM,CACL,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,WAAW,EAChE,KAAK,CAAC,oCAAoC,CAC1C,CAAC;QAEF,4GAA4G;QAC5G,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;YACrB,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACpD,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC3D,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC9C,CAAC;QACF,CAAC;IACF,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,GAAG,QAAkB;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC/B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC7C,MAAM,IAAI,UAAU,CAAC,2BAA2B,EAAE,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YAClF,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACrC,qGAAqG;gBACrG,iGAAiG;gBACjG,iGAAiG;gBACjG,8CAA8C;gBAC9C,sGAAsG;gBACtG,qBAAqB;gBACrB,MAAM,IAAI,UAAU,CAAC,8BAA8B,EAAE,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YACrF,CAAC;YACD,0GAA0G;YAC1G,yGAAyG;YACzG,+CAA+C;YAC/C,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,kDAAkD,CAAC,CAAC;YACzE,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACrD,MAAM,IAAI,UAAU,CAAC,uBAAuB,EAAE,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YAC9E,CAAC;QACF,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;IACxC,CAAC;IAEM,WAAW;QACjB,OAAO,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,CAAC;IACD,oCAAoC;IAC5B,KAAK,CAAC,YAAY,CAAC,QAAkB;QAC5C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,UAAU,GAAoB,EAAE,CAAC;YACvC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAChC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;YAChD,CAAC;YACD,MAAM,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAE9B,sEAAsE;YACtE,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAChC,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;gBAEjD,wDAAwD;gBACxD,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,KAAK,CAAC,iCAAiC,CAAC,CAAC;YAC3E,CAAC;QACF,CAAC;IACF,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,QAAkB;QAC3C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,SAAS,GAAoB,EAAE,CAAC;YACtC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAChC,wDAAwD;gBACxD,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC1C,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;YAC/C,CAAC;YACD,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC9B,CAAC;IACF,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,QAAkB;QAC1C,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC,+CAA+C,CAAC,CAAC;QAC/E,MAAM,MAAM,GAAoB,EAAE,CAAC;QACnC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAEO,eAAe,CAAC,GAAW;QAClC,OAAO,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnD,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,GAAW,EAAE,QAAuB;QAC3D,MAAM,IAAI,CAAC,2BAA2B,CAAC,KAAK,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC7D,CAAC;IAEO,UAAU;QACjB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;QACxC,yEAAyE;QACzE,6FAA6F;QAC7F,6DAA6D;QAC7D,kEAAkE;QAClE,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,KAAK,EAAE,QAAgB,EAAE,EAAE;YACpD,sFAAsF;YACtF,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,UAAU;gBAAE,OAAO;YAC3D,sGAAsG;YACtG,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;gBACrB,MAAM,KAAK,GAAuB,EAAE,CAAC;gBACrC,MAAM,SAAS,GAAa,EAAE,CAAC;gBAC/B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,2BAA2B,CAAC,IAAI,EAAE,EAAE,CAAC;oBAC/D,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;wBAChD,IAAI,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;4BAC5C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;wBACpD,CAAC;6BAAM,CAAC;4BACP,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;wBACzB,CAAC;oBACF,CAAC;gBACF,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;gBACvC,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;oBACxC,IAAI,CAAC,cAAc,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;gBAChE,CAAC,CAAC,CAAC;YACJ,CAAC;QACF,CAAC,CAAC,CAAC;QAEH,mFAAmF;QACnF,gFAAgF;QAChF,IAAI,CAAC,2BAA2B,CAAC,EAAE,CAClC,eAAe;QACf,kEAAkE;QAClE,KAAK,EAAE,GAAW,EAAE,aAA4B,EAAE,EAAE;YACnD,mCAAmC;YACnC,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,aAAa,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACxD,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACP,4DAA4D;gBAC5D,wCAAwC;gBACxC,kEAAkE;gBAClE,0EAA0E;gBAC1E,iDAAiD;gBACjD,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;oBACvC,MAAM,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;gBACjD,CAAC,CAAC,CAAC;YACJ,CAAC;QACF,CAAC,CACD,CAAC;QAEF,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;YACrB,IAAI,CAAC,cAAc,EAAE,CAAC;QACvB,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE;YACjC,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;gBACrB,IAAI,CAAC,cAAc,EAAE,CAAC;YACvB,CAAC;QACF,CAAC,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,KAAK,WAAW,CAAC,QAAQ,EAAE,CAAC;YACvD,IAAI,CAAC,OAAO;iBACV,YAAY,EAAE;iBACd,IAAI,CAAC,GAAG,EAAE;gBACV,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC1B,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBAChB,IAAI,CAAC,cAAc,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;YAChE,CAAC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE;YACpC,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,KAAK,WAAW,CAAC,QAAQ,EAAE,CAAC;gBACvD,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC1B,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IAEO,iBAAiB,CAAC,GAAW;QACpC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC3E,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC,cAAc,CAAC,+BAA+B,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACzB,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACxB,IAAI,CAAC,cAAc,CAAC,2BAA2B,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9D,CAAC,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,GAAW,EAAE,aAA4B;QACvE,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QAC5B,CAAC;QACD,MAAM,CAAC,aAAa,KAAK,SAAS,EAAE,KAAK,CAAC,2BAA2B,CAAC,CAAC;QACvE,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;YACrB,+CAA+C;YAC/C,qDAAqD;YACrD,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC5B,IAAI,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxC,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC1C,CAAC;YACF,CAAC;YACD,2CAA2C;YAC3C,kEAAkE;YAClE,uFAAuF;iBAClF,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC1E,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACjC,CAAC;QACF,CAAC;IACF,CAAC;IACD,mCAAmC;IAE3B,QAAQ;QACf,oDAAoD;QACpD,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,KAAK,WAAW,CAAC,QAAQ,EAAE,CAAC;YACvD,OAAO,IAAI,CAAC;QACb,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YAC7B,OAAO,KAAK,CAAC;QACd,CAAC;QAED,iGAAiG;QACjG,gFAAgF;QAEhF,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC;IACzC,CAAC;IAEO,cAAc;QACrB,qEAAqE;QACrE,gDAAgD;QAChD,MAAM,eAAe,GAAa,EAAE,CAAC;QACrC,MAAM,KAAK,GAAuB,EAAE,CAAC;QAErC,KAAK,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACnD,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YACpD,CAAC;QACF,CAAC;QAED,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,2BAA2B,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/D,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YACpD,IAAI,aAAa,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,SAAS,EAAE,CAAC;gBACtF,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/B,CAAC;QACF,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC;QAE7C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YAClC,IAAI,CAAC,cAAc,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;IACJ,CAAC;IAEO,iBAAiB;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC;QAChC,IAAI,CAAC,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;QAEtC,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;YACrB,sGAAsG;YACtG,iFAAiF;YACjF,IAAI,CAAC,cAAc,EAAE,CAAC;QACvB,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACzB,CAAC;IACF,CAAC;IAEO,cAAc,CAAC,SAAiB,EAAE,KAAc,EAAE,GAAY;QACrE,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;IACvD,CAAC;CACD;AAED,MAAM,qBAAsB,SAAQ,qBAAqB;IACxD,YACC,gBAAwC,EACxC,oBAA2C,EAC3C,QAAiB;QAEjB,KAAK,CAAC,gBAAgB,EAAE,oBAAoB,EAAE,QAAQ,EAAE,KAAK,IAAI,EAAE,CAClE,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,gBAAgB,EAAE,QAAQ,CAAC,CACrD,CAAC;IACH,CAAC;IACM,KAAK,CAAC,OAAO,CAAC,OAAiB;QACrC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,KAAK,EAAE,IAAI,OAAO,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;YAC5E,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;YACnD,MAAM,CACL,cAAc,KAAK,SAAS,EAC5B,KAAK,CAAC,8EAA8E,CACpF,CAAC;YAEF,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC;QACzE,CAAC;QACD,OAAO,QAAQ,CAAC;IACjB,CAAC;CACD;AAED;;;GAGG;AACH,MAAM,OAAO,qBAAqB;IAAlC;QAEiB,SAAI,GAAG,qBAAqB,CAAC,IAAI,CAAC;IAsCnD,CAAC;IApCA,IAAW,sBAAsB;QAChC,OAAO,IAAI,CAAC;IACb,CAAC;IAEM,MAAM,KAAK,aAAa;QAC9B,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,qBAAqB,EAAE,CAAC,CAAC,CAAC;IAClE,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,mBAAmB,CACtC,aAAqC;QAErC,MAAM,WAAW,GAAG,CAAC,GAAG,aAAa,CAAC,WAAW,EAAE,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC/E,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,gBAAgB,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QACpF,MAAM,UAAU,GAAiC,MAAM,SAAS,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;QAElF,8GAA8G;QAC9G,6FAA6F;QAC7F,MAAM,CACL,UAAU,CAAC,eAAe,KAAK,SAAS,EACxC,KAAK,CAAC,2DAA2D,CACjE,CAAC;QACF,OAAO,UAAuC,CAAC;IAChD,CAAC;IAEM,KAAK,CAAC,oBAAoB,CAChC,OAA+B,EAC/B,QAAiB;QAEjB,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC;QAC1C,MAAM,kCAAkC,GAAG,2BAA2B,CAAC,UAAU,EAAE,CAAC;QACpF,MAAM,SAAS,GAAG,IAAI,GAAG,EAA2B,CAAC;QACrD,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC3C,SAAS,CAAC,GAAG,CAAC,kCAAkC,CAAC,IAAI,EAAE,kCAAkC,CAAC,CAAC;QAE3F,OAAO,IAAI,qBAAqB,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAChE,CAAC;;AAtCsB,0BAAI,GAAG,YAAY,AAAf,CAAgB","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport type {\n\tFluidObject,\n\tIFluidHandle,\n\tIFluidLoadable,\n\tIRequest,\n\tIResponse,\n} from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport {\n\tFluidDataStoreRuntime,\n\tFluidObjectHandle,\n\ttype ISharedObjectRegistry,\n} from \"@fluidframework/datastore/internal\";\nimport type {\n\tIChannelFactory,\n\tIFluidDataStoreRuntime,\n} from \"@fluidframework/datastore-definitions/internal\";\nimport { type ISharedMap, type IValueChanged, SharedMap } from \"@fluidframework/map/internal\";\nimport { ConsensusRegisterCollection } from \"@fluidframework/register-collection/internal\";\nimport type {\n\tIFluidDataStoreContext,\n\tIFluidDataStoreFactory,\n\tNamedFluidDataStoreRegistryEntry,\n} from \"@fluidframework/runtime-definitions/internal\";\nimport {\n\ttype ITelemetryLoggerExt,\n\tUsageError,\n\tcreateChildLogger,\n\ttagCodeArtifacts,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { v4 as uuid } from \"uuid\";\n\nimport type { IAgentScheduler, IAgentSchedulerEvents } from \"./agent.js\";\n\n// Note: making sure this ID is unique and does not collide with storage provided clientID\nconst UnattachedClientId = `${uuid()}_unattached`;\n\nconst mapWait = async <T = unknown>(map: ISharedMap, key: string): Promise<T> => {\n\tconst maybeValue = map.get<T>(key);\n\tif (maybeValue !== undefined) {\n\t\treturn maybeValue;\n\t}\n\n\treturn new Promise((resolve) => {\n\t\tconst handler = (changed: IValueChanged): void => {\n\t\t\tif (changed.key === key) {\n\t\t\t\tmap.off(\"valueChanged\", handler);\n\t\t\t\tconst value = map.get<T>(changed.key);\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tthrow new Error(\"Unexpected valueChanged result\");\n\t\t\t\t}\n\t\t\t\tresolve(value);\n\t\t\t}\n\t\t};\n\t\tmap.on(\"valueChanged\", handler);\n\t});\n};\n\nconst schedulerId = \"scheduler\";\n\nexport class AgentScheduler\n\textends TypedEventEmitter<IAgentSchedulerEvents>\n\timplements IAgentScheduler\n{\n\tpublic static async load(\n\t\truntime: IFluidDataStoreRuntime,\n\t\tcontext: IFluidDataStoreContext,\n\t\texisting: boolean,\n\t): Promise<IAgentScheduler> {\n\t\tlet root: ISharedMap;\n\t\tlet consensusRegisterCollection: ConsensusRegisterCollection<string | null>;\n\t\tif (existing) {\n\t\t\troot = (await runtime.getChannel(\"root\")) as ISharedMap;\n\t\t\tconst handle = await mapWait<IFluidHandle<ConsensusRegisterCollection<string | null>>>(\n\t\t\t\troot,\n\t\t\t\tschedulerId,\n\t\t\t);\n\t\t\tassert(handle !== undefined, 0x116 /* \"Missing handle on scheduler load\" */);\n\t\t\tconsensusRegisterCollection = await handle.get();\n\t\t} else {\n\t\t\troot = SharedMap.create(runtime, \"root\");\n\t\t\troot.bindToContext();\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\tconsensusRegisterCollection = ConsensusRegisterCollection.create(runtime);\n\t\t\tconsensusRegisterCollection.bindToContext();\n\t\t\troot.set(schedulerId, consensusRegisterCollection.handle);\n\t\t}\n\t\tconst agentScheduler = new AgentScheduler(runtime, context, consensusRegisterCollection);\n\t\tagentScheduler.initialize();\n\n\t\treturn agentScheduler;\n\t}\n\n\tpublic get IAgentScheduler(): IAgentScheduler {\n\t\treturn this;\n\t}\n\tpublic get IFluidLoadable(): IFluidLoadable {\n\t\treturn this;\n\t}\n\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tprivate get clientId(): string {\n\t\tif (this.runtime.attachState === AttachState.Detached) {\n\t\t\treturn UnattachedClientId;\n\t\t}\n\t\tconst clientId = this.runtime.clientId;\n\t\tassert(!!clientId, 0x117 /* \"Trying to get missing clientId!\" */);\n\t\treturn clientId;\n\t}\n\n\t// Set of tasks registered by this client.\n\t// Has no relationship with lists below.\n\t// The only requirement here - a task can be registered by a client only once.\n\t// Other clients can pick these tasks.\n\tprivate readonly registeredTasks = new Set<string>();\n\n\t// List of all tasks client is capable of running (essentially expressed desire to run)\n\t// Client will proactively attempt to pick them up these tasks if they are not assigned to other clients.\n\t// This is a strict superset of tasks running in the client.\n\tprivate readonly locallyRunnableTasks = new Map<string, () => Promise<void>>();\n\n\t// Set of registered tasks client is currently running.\n\t// It's subset of this.locallyRunnableTasks\n\tprivate runningTasks = new Set<string>();\n\n\tprivate readonly _handle: IFluidHandle<this>;\n\n\tconstructor(\n\t\tprivate readonly runtime: IFluidDataStoreRuntime,\n\t\tprivate readonly context: IFluidDataStoreContext,\n\t\tprivate readonly consensusRegisterCollection: ConsensusRegisterCollection<string | null>,\n\t) {\n\t\tsuper();\n\t\tthis.logger = createChildLogger({ logger: runtime.logger });\n\t\t// We are expecting this class to have many listeners, so we suppress noisy \"MaxListenersExceededWarning\" logging.\n\t\tsuper.setMaxListeners(0);\n\t\tthis._handle = new FluidObjectHandle(this, \"\", this.runtime.objectsRoutingContext);\n\t}\n\n\tpublic get handle(): IFluidHandle<this> {\n\t\treturn this._handle;\n\t}\n\n\tpublic async register(...taskUrls: string[]): Promise<void> {\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tif (this.registeredTasks.has(taskUrl)) {\n\t\t\t\tthrow new UsageError(`Task is already registered`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t}\n\t\tconst unregisteredTasks: string[] = [];\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tthis.registeredTasks.add(taskUrl);\n\t\t\t// Only register for a new task.\n\t\t\tconst currentClient = this.getTaskClientId(taskUrl);\n\t\t\tif (currentClient === undefined) {\n\t\t\t\tunregisteredTasks.push(taskUrl);\n\t\t\t}\n\t\t}\n\t\treturn this.registerCore(unregisteredTasks);\n\t}\n\n\tpublic async pick(taskUrl: string, worker: () => Promise<void>): Promise<void> {\n\t\tif (this.locallyRunnableTasks.has(taskUrl)) {\n\t\t\tthrow new UsageError(`Task is already attempted`, tagCodeArtifacts({ taskUrl }));\n\t\t}\n\t\tthis.locallyRunnableTasks.set(taskUrl, worker);\n\n\t\t// We have a policy to disallow non-interactive clients from taking tasks. Callers of pick() can\n\t\t// either perform this check proactively and call conditionally, or catch the error (in which case\n\t\t// they can know they will not get the task).\n\t\tassert(\n\t\t\tthis.context.deltaManager.clientDetails.capabilities.interactive,\n\t\t\t0x118 /* \"Bad client interactive check\" */,\n\t\t);\n\n\t\t// Check the current status and express interest if it's a new one (undefined) or currently unpicked (null).\n\t\tif (this.isActive()) {\n\t\t\tconst currentClient = this.getTaskClientId(taskUrl);\n\t\t\tif (currentClient === undefined || currentClient === null) {\n\t\t\t\tawait this.writeCore(taskUrl, this.clientId);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async release(...taskUrls: string[]): Promise<void> {\n\t\tconst active = this.isActive();\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tif (!this.locallyRunnableTasks.has(taskUrl)) {\n\t\t\t\tthrow new UsageError(`Task was never registered`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t\tif (!this.runningTasks.has(taskUrl)) {\n\t\t\t\t// If we got disconnected (and are attached), tasks that we WERE picked for at the time of disconnect\n\t\t\t\t// will still show us as holding the task according to getTaskClientId (the CRC is stale), but we\n\t\t\t\t// should not try to release because our disconnect will already result in either someone else or\n\t\t\t\t// ourselves clearing the task upon reconnect.\n\t\t\t\t// This UsageError is to enforce that the caller should check AgentScheduler.pickedTasks before trying\n\t\t\t\t// to release a task.\n\t\t\t\tthrow new UsageError(`Task is not currently picked`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t\t// We may only release tasks that we KNOW we hold (detached state or connected and own the CRC). If we're\n\t\t\t// attached+disconnected then we'll lose the task automatically, and so may not release manually (someone\n\t\t\t// else might hold it by the time we reconnect)\n\t\t\tassert(active, 0x119 /* \"This agent became inactive while releasing\" */);\n\t\t\tif (this.getTaskClientId(taskUrl) !== this.clientId) {\n\t\t\t\tthrow new UsageError(`Task was never picked`, tagCodeArtifacts({ taskUrl }));\n\t\t\t}\n\t\t}\n\t\treturn this.releaseCore([...taskUrls]);\n\t}\n\n\tpublic pickedTasks(): string[] {\n\t\treturn [...this.runningTasks.values()];\n\t}\n\t/* eslint-disable unicorn/no-null */\n\tprivate async registerCore(taskUrls: string[]): Promise<void> {\n\t\tif (taskUrls.length > 0) {\n\t\t\tconst registersP: Promise<void>[] = [];\n\t\t\tfor (const taskUrl of taskUrls) {\n\t\t\t\tregistersP.push(this.writeCore(taskUrl, null));\n\t\t\t}\n\t\t\tawait Promise.all(registersP);\n\n\t\t\t// The registers should have up to date results now. Check the status.\n\t\t\tfor (const taskUrl of taskUrls) {\n\t\t\t\tconst taskStatus = this.getTaskClientId(taskUrl);\n\n\t\t\t\t// Task should be either registered (null) or picked up.\n\t\t\t\tassert(taskStatus !== undefined, 0x11a /* `Unsuccessful registration` */);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async releaseCore(taskUrls: string[]): Promise<void> {\n\t\tif (taskUrls.length > 0) {\n\t\t\tconst releasesP: Promise<void>[] = [];\n\t\t\tfor (const taskUrl of taskUrls) {\n\t\t\t\t// Remove from local map so that it can be picked later.\n\t\t\t\tthis.locallyRunnableTasks.delete(taskUrl);\n\t\t\t\treleasesP.push(this.writeCore(taskUrl, null));\n\t\t\t}\n\t\t\tawait Promise.all(releasesP);\n\t\t}\n\t}\n\n\tprivate async clearTasks(taskUrls: string[]): Promise<void> {\n\t\tassert(this.isActive(), 0x11b /* \"Trying to clear tasks on inactive agent\" */);\n\t\tconst clearP: Promise<void>[] = [];\n\t\tfor (const taskUrl of taskUrls) {\n\t\t\tclearP.push(this.writeCore(taskUrl, null));\n\t\t}\n\t\tawait Promise.all(clearP);\n\t}\n\n\tprivate getTaskClientId(url: string): string | null | undefined {\n\t\treturn this.consensusRegisterCollection.read(url);\n\t}\n\n\tprivate async writeCore(key: string, clientId: string | null): Promise<void> {\n\t\tawait this.consensusRegisterCollection.write(key, clientId);\n\t}\n\n\tprivate initialize(): void {\n\t\tconst quorum = this.runtime.getQuorum();\n\t\t// A client left the quorum. Iterate and clear tasks held by that client.\n\t\t// Ideally a leader should do this cleanup. But it's complicated when a leader itself leaves.\n\t\t// Probably okay for now to have every client try to do this.\n\t\t// eslint-disable-next-line @typescript-eslint/no-misused-promises\n\t\tquorum.on(\"removeMember\", async (clientId: string) => {\n\t\t\t// TODO AB#19980: The scenario with a detached routing context is not fully supported.\n\t\t\tif (!this.runtime.objectsRoutingContext.isAttached) return;\n\t\t\t// Cleanup only if connected. If not, cleanup will happen in initializeCore() that runs on connection.\n\t\t\tif (this.isActive()) {\n\t\t\t\tconst tasks: Promise<unknown>[] = [];\n\t\t\t\tconst leftTasks: string[] = [];\n\t\t\t\tfor (const taskUrl of this.consensusRegisterCollection.keys()) {\n\t\t\t\t\tif (this.getTaskClientId(taskUrl) === clientId) {\n\t\t\t\t\t\tif (this.locallyRunnableTasks.has(taskUrl)) {\n\t\t\t\t\t\t\ttasks.push(this.writeCore(taskUrl, this.clientId));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tleftTasks.push(taskUrl);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttasks.push(this.clearTasks(leftTasks));\n\t\t\t\tawait Promise.all(tasks).catch((error) => {\n\t\t\t\t\tthis.sendErrorEvent(\"AgentScheduler_RemoveMemberError\", error);\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\t// Listeners for new/released tasks. All clients will try to grab at the same time.\n\t\t// May be we want a randomized timer (Something like raft) to reduce chattiness?\n\t\tthis.consensusRegisterCollection.on(\n\t\t\t\"atomicChanged\",\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-misused-promises\n\t\t\tasync (key: string, currentClient: string | null) => {\n\t\t\t\t// Check if this client was chosen.\n\t\t\t\tif (this.isActive() && currentClient === this.clientId) {\n\t\t\t\t\tthis.onNewTaskAssigned(key);\n\t\t\t\t} else {\n\t\t\t\t\t// The call below mutates the consensusRegisterCollection in\n\t\t\t\t\t// its event handler, which is not safe.\n\t\t\t\t\t// We need to force this to be part of a different batch of ops by\n\t\t\t\t\t// scheduling a microtask in order to work around the current validations.\n\t\t\t\t\t// This is not recommended and should be avoided.\n\t\t\t\t\tawait Promise.resolve().then(async () => {\n\t\t\t\t\t\tawait this.onTaskReassigned(key, currentClient);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\tif (this.isActive()) {\n\t\t\tthis.initializeCore();\n\t\t}\n\n\t\tthis.runtime.on(\"connected\", () => {\n\t\t\tif (this.isActive()) {\n\t\t\t\tthis.initializeCore();\n\t\t\t}\n\t\t});\n\n\t\tif (this.runtime.attachState === AttachState.Detached) {\n\t\t\tthis.runtime\n\t\t\t\t.waitAttached()\n\t\t\t\t.then(() => {\n\t\t\t\t\tthis.clearRunningTasks();\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tthis.sendErrorEvent(\"AgentScheduler_clearRunningTasks\", error);\n\t\t\t\t});\n\t\t}\n\n\t\tthis.runtime.on(\"disconnected\", () => {\n\t\t\tif (this.runtime.attachState !== AttachState.Detached) {\n\t\t\t\tthis.clearRunningTasks();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate onNewTaskAssigned(key: string): void {\n\t\tassert(!this.runningTasks.has(key), 0x11d /* \"task is already running\" */);\n\t\tthis.runningTasks.add(key);\n\t\tconst worker = this.locallyRunnableTasks.get(key);\n\t\tif (worker === undefined) {\n\t\t\tthis.sendErrorEvent(\"AgentScheduler_UnwantedChange\", undefined, key);\n\t\t} else {\n\t\t\tthis.emit(\"picked\", key);\n\t\t\tworker().catch((error) => {\n\t\t\t\tthis.sendErrorEvent(\"AgentScheduler_FailedWork\", error, key);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async onTaskReassigned(key: string, currentClient: string | null): Promise<void> {\n\t\tif (this.runningTasks.has(key)) {\n\t\t\tthis.runningTasks.delete(key);\n\t\t\tthis.emit(\"released\", key);\n\t\t}\n\t\tassert(currentClient !== undefined, 0x11e /* \"client is undefined\" */);\n\t\tif (this.isActive()) {\n\t\t\t// attempt to pick up task if we are connected.\n\t\t\t// If not, initializeCore() will do it when connected\n\t\t\tif (currentClient === null) {\n\t\t\t\tif (this.locallyRunnableTasks.has(key)) {\n\t\t\t\t\tawait this.writeCore(key, this.clientId);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Check if the op came from dropped client\n\t\t\t// This could happen when \"old\" ops are submitted on reconnection.\n\t\t\t// They carry \"old\" ref seq number, but if write is not contested, it will get accepted\n\t\t\telse if (this.runtime.getQuorum().getMember(currentClient) === undefined) {\n\t\t\t\tawait this.writeCore(key, null);\n\t\t\t}\n\t\t}\n\t}\n\t/* eslint-enable unicorn/no-null */\n\n\tprivate isActive(): boolean {\n\t\t// Scheduler should be active in detached container.\n\t\tif (this.runtime.attachState === AttachState.Detached) {\n\t\t\treturn true;\n\t\t}\n\t\tif (!this.runtime.connected) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Note: we are not checking for this.context.deltaManager.clientDetails.capabilities.interactive\n\t\t// here. Instead we assert in pick() if a non-interactive client tries to pick.\n\n\t\treturn this.context.deltaManager.active;\n\t}\n\n\tprivate initializeCore(): void {\n\t\t// Nobody released the tasks held by last client in previous session.\n\t\t// Check to see if this client needs to do this.\n\t\tconst clearCandidates: string[] = [];\n\t\tconst tasks: Promise<unknown>[] = [];\n\n\t\tfor (const [taskUrl] of this.locallyRunnableTasks) {\n\t\t\tif (!this.getTaskClientId(taskUrl)) {\n\t\t\t\ttasks.push(this.writeCore(taskUrl, this.clientId));\n\t\t\t}\n\t\t}\n\n\t\tfor (const taskUrl of this.consensusRegisterCollection.keys()) {\n\t\t\tconst currentClient = this.getTaskClientId(taskUrl);\n\t\t\tif (currentClient && this.runtime.getQuorum().getMember(currentClient) === undefined) {\n\t\t\t\tclearCandidates.push(taskUrl);\n\t\t\t}\n\t\t}\n\n\t\ttasks.push(this.clearTasks(clearCandidates));\n\n\t\tPromise.all(tasks).catch((error) => {\n\t\t\tthis.sendErrorEvent(\"AgentScheduler_InitError\", error);\n\t\t});\n\t}\n\n\tprivate clearRunningTasks(): void {\n\t\tconst tasks = this.runningTasks;\n\t\tthis.runningTasks = new Set<string>();\n\n\t\tif (this.isActive()) {\n\t\t\t// Clear all tasks with UnattachedClientId (if was unattached) and reapply for tasks with new clientId\n\t\t\t// If we are simply disconnected, then proper cleanup will be done on connection.\n\t\t\tthis.initializeCore();\n\t\t}\n\n\t\tfor (const task of tasks) {\n\t\t\tthis.emit(\"lost\", task);\n\t\t}\n\t}\n\n\tprivate sendErrorEvent(eventName: string, error: unknown, key?: string): void {\n\t\tthis.logger.sendErrorEvent({ eventName, key }, error);\n\t}\n}\n\nclass AgentSchedulerRuntime extends FluidDataStoreRuntime {\n\tconstructor(\n\t\tdataStoreContext: IFluidDataStoreContext,\n\t\tsharedObjectRegistry: ISharedObjectRegistry,\n\t\texisting: boolean,\n\t) {\n\t\tsuper(dataStoreContext, sharedObjectRegistry, existing, async () =>\n\t\t\tAgentScheduler.load(this, dataStoreContext, existing),\n\t\t);\n\t}\n\tpublic async request(request: IRequest): Promise<IResponse> {\n\t\tconst response = await super.request(request);\n\t\tif (response.status === 404 && (request.url === \"\" || request.url === \"/\")) {\n\t\t\tconst agentScheduler = await this.entryPoint.get();\n\t\t\tassert(\n\t\t\t\tagentScheduler !== undefined,\n\t\t\t\t0x466 /* entryPoint for AgentSchedulerRuntime should have been initialized by now */,\n\t\t\t);\n\n\t\t\treturn { status: 200, mimeType: \"fluid/object\", value: agentScheduler };\n\t\t}\n\t\treturn response;\n\t}\n}\n\n/**\n * @legacy\n * @beta\n */\nexport class AgentSchedulerFactory implements IFluidDataStoreFactory {\n\tpublic static readonly type = \"_scheduler\";\n\tpublic readonly type = AgentSchedulerFactory.type;\n\n\tpublic get IFluidDataStoreFactory(): AgentSchedulerFactory {\n\t\treturn this;\n\t}\n\n\tpublic static get registryEntry(): NamedFluidDataStoreRegistryEntry {\n\t\treturn [this.type, Promise.resolve(new AgentSchedulerFactory())];\n\t}\n\n\tpublic static async createChildInstance(\n\t\tparentContext: IFluidDataStoreContext,\n\t): Promise<IAgentScheduler> {\n\t\tconst packagePath = [...parentContext.packagePath, AgentSchedulerFactory.type];\n\t\tconst dataStore = await parentContext.containerRuntime.createDataStore(packagePath);\n\t\tconst entryPoint: FluidObject<IAgentScheduler> = await dataStore.entryPoint.get();\n\n\t\t// AgentSchedulerRuntime always puts an AgentScheduler object in the data store's entryPoint, but double-check\n\t\t// while we plumb entryPoints correctly everywhere, so we can be sure the cast below is fine.\n\t\tassert(\n\t\t\tentryPoint.IAgentScheduler !== undefined,\n\t\t\t0x467 /* The data store's entryPoint is not an AgentScheduler! */,\n\t\t);\n\t\treturn entryPoint as unknown as AgentScheduler;\n\t}\n\n\tpublic async instantiateDataStore(\n\t\tcontext: IFluidDataStoreContext,\n\t\texisting: boolean,\n\t): Promise<FluidDataStoreRuntime> {\n\t\tconst mapFactory = SharedMap.getFactory();\n\t\tconst consensusRegisterCollectionFactory = ConsensusRegisterCollection.getFactory();\n\t\tconst dataTypes = new Map<string, IChannelFactory>();\n\t\tdataTypes.set(mapFactory.type, mapFactory);\n\t\tdataTypes.set(consensusRegisterCollectionFactory.type, consensusRegisterCollectionFactory);\n\n\t\treturn new AgentSchedulerRuntime(context, dataTypes, existing);\n\t}\n}\n"]}
@@ -8,7 +8,7 @@ import type { IAgentScheduler } from "./agent.js";
8
8
  /**
9
9
  * Events emitted by {@link TaskSubscription}.
10
10
  * @legacy
11
- * @alpha
11
+ * @beta
12
12
  */
13
13
  export interface ITaskSubscriptionEvents extends IEvent {
14
14
  (event: "gotTask" | "lostTask", listener: () => void): any;
@@ -16,7 +16,7 @@ export interface ITaskSubscriptionEvents extends IEvent {
16
16
  /**
17
17
  * TaskSubscription works with an AgentScheduler to make it easier to monitor a specific task ownership.
18
18
  * @legacy
19
- * @alpha
19
+ * @beta
20
20
  */
21
21
  export declare class TaskSubscription extends TypedEventEmitter<ITaskSubscriptionEvents> {
22
22
  private readonly agentScheduler;
@@ -6,7 +6,7 @@ import { TypedEventEmitter } from "@fluid-internal/client-utils";
6
6
  /**
7
7
  * TaskSubscription works with an AgentScheduler to make it easier to monitor a specific task ownership.
8
8
  * @legacy
9
- * @alpha
9
+ * @beta
10
10
  */
11
11
  export class TaskSubscription extends TypedEventEmitter {
12
12
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"taskSubscription.js","sourceRoot":"","sources":["../src/taskSubscription.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAcjE;;;;GAIG;AACH,MAAM,OAAO,gBAAiB,SAAQ,iBAA0C;IAG/E;;;OAGG;IACH,YACkB,cAA+B,EAChC,MAAc;QAE9B,KAAK,EAAE,CAAC;QAHS,mBAAc,GAAd,cAAc,CAAiB;QAChC,WAAM,GAAN,MAAM,CAAQ;QARvB,eAAU,GAAY,KAAK,CAAC;QAWnC,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAe,EAAE,EAAE;YAC/C,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtB,CAAC;QACF,CAAC,CAAC,CAAC;QACH,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,OAAe,EAAE,EAAE;YACjD,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvB,CAAC;QACF,CAAC,CAAC,CAAC;QACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,OAAe,EAAE,EAAE;YAC7C,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvB,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACI,QAAQ;QACd,OAAO,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChE,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACtB,uFAAuF;YACvF,gFAAgF;YAChF,0FAA0F;YAC1F,qCAAqC;YACrC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACtE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACxB,CAAC;IACF,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IEvent } from \"@fluidframework/core-interfaces\";\n\nimport type { IAgentScheduler } from \"./agent.js\";\n\n/**\n * Events emitted by {@link TaskSubscription}.\n * @legacy\n * @alpha\n */\nexport interface ITaskSubscriptionEvents extends IEvent {\n\t(event: \"gotTask\" | \"lostTask\", listener: () => void);\n}\n\n/**\n * TaskSubscription works with an AgentScheduler to make it easier to monitor a specific task ownership.\n * @legacy\n * @alpha\n */\nexport class TaskSubscription extends TypedEventEmitter<ITaskSubscriptionEvents> {\n\tprivate subscribed: boolean = false;\n\n\t/**\n\t * @param agentScheduler - The AgentScheduler that will be subscribed against\n\t * @param taskId - The string ID of the task to subscribe against\n\t */\n\tconstructor(\n\t\tprivate readonly agentScheduler: IAgentScheduler,\n\t\tpublic readonly taskId: string,\n\t) {\n\t\tsuper();\n\t\tagentScheduler.on(\"picked\", (_taskId: string) => {\n\t\t\tif (_taskId === this.taskId) {\n\t\t\t\tthis.emit(\"gotTask\");\n\t\t\t}\n\t\t});\n\t\tagentScheduler.on(\"released\", (_taskId: string) => {\n\t\t\tif (_taskId === this.taskId) {\n\t\t\t\tthis.emit(\"lostTask\");\n\t\t\t}\n\t\t});\n\t\tagentScheduler.on(\"lost\", (_taskId: string) => {\n\t\t\tif (_taskId === this.taskId) {\n\t\t\t\tthis.emit(\"lostTask\");\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Check if currently holding ownership of the task.\n\t * @returns true if currently the task owner, false otherwise.\n\t */\n\tpublic haveTask(): boolean {\n\t\treturn this.agentScheduler.pickedTasks().includes(this.taskId);\n\t}\n\n\t/**\n\t * Volunteer for the task. By default, the TaskSubscription will only watch the task and not volunteer.\n\t * This is safe to call multiple times across multiple TaskSubscriptions.\n\t */\n\tpublic volunteer(): void {\n\t\tif (!this.subscribed) {\n\t\t\t// AgentScheduler throws if the same task is picked twice but we don't care because our\n\t\t\t// worker does nothing. We only care that the AgentScheduler is trying to pick.\n\t\t\t// We also don't care if we throw due to failing the interactive check, because then we'll\n\t\t\t// just appear to never get the task.\n\t\t\tthis.agentScheduler.pick(this.taskId, async () => {}).catch(() => {});\n\t\t\tthis.subscribed = true;\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"taskSubscription.js","sourceRoot":"","sources":["../src/taskSubscription.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAcjE;;;;GAIG;AACH,MAAM,OAAO,gBAAiB,SAAQ,iBAA0C;IAG/E;;;OAGG;IACH,YACkB,cAA+B,EAChC,MAAc;QAE9B,KAAK,EAAE,CAAC;QAHS,mBAAc,GAAd,cAAc,CAAiB;QAChC,WAAM,GAAN,MAAM,CAAQ;QARvB,eAAU,GAAY,KAAK,CAAC;QAWnC,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAe,EAAE,EAAE;YAC/C,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtB,CAAC;QACF,CAAC,CAAC,CAAC;QACH,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,OAAe,EAAE,EAAE;YACjD,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvB,CAAC;QACF,CAAC,CAAC,CAAC;QACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,OAAe,EAAE,EAAE;YAC7C,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvB,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACI,QAAQ;QACd,OAAO,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChE,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACtB,uFAAuF;YACvF,gFAAgF;YAChF,0FAA0F;YAC1F,qCAAqC;YACrC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACtE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACxB,CAAC;IACF,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IEvent } from \"@fluidframework/core-interfaces\";\n\nimport type { IAgentScheduler } from \"./agent.js\";\n\n/**\n * Events emitted by {@link TaskSubscription}.\n * @legacy\n * @beta\n */\nexport interface ITaskSubscriptionEvents extends IEvent {\n\t(event: \"gotTask\" | \"lostTask\", listener: () => void);\n}\n\n/**\n * TaskSubscription works with an AgentScheduler to make it easier to monitor a specific task ownership.\n * @legacy\n * @beta\n */\nexport class TaskSubscription extends TypedEventEmitter<ITaskSubscriptionEvents> {\n\tprivate subscribed: boolean = false;\n\n\t/**\n\t * @param agentScheduler - The AgentScheduler that will be subscribed against\n\t * @param taskId - The string ID of the task to subscribe against\n\t */\n\tconstructor(\n\t\tprivate readonly agentScheduler: IAgentScheduler,\n\t\tpublic readonly taskId: string,\n\t) {\n\t\tsuper();\n\t\tagentScheduler.on(\"picked\", (_taskId: string) => {\n\t\t\tif (_taskId === this.taskId) {\n\t\t\t\tthis.emit(\"gotTask\");\n\t\t\t}\n\t\t});\n\t\tagentScheduler.on(\"released\", (_taskId: string) => {\n\t\t\tif (_taskId === this.taskId) {\n\t\t\t\tthis.emit(\"lostTask\");\n\t\t\t}\n\t\t});\n\t\tagentScheduler.on(\"lost\", (_taskId: string) => {\n\t\t\tif (_taskId === this.taskId) {\n\t\t\t\tthis.emit(\"lostTask\");\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Check if currently holding ownership of the task.\n\t * @returns true if currently the task owner, false otherwise.\n\t */\n\tpublic haveTask(): boolean {\n\t\treturn this.agentScheduler.pickedTasks().includes(this.taskId);\n\t}\n\n\t/**\n\t * Volunteer for the task. By default, the TaskSubscription will only watch the task and not volunteer.\n\t * This is safe to call multiple times across multiple TaskSubscriptions.\n\t */\n\tpublic volunteer(): void {\n\t\tif (!this.subscribed) {\n\t\t\t// AgentScheduler throws if the same task is picked twice but we don't care because our\n\t\t\t// worker does nothing. We only care that the AgentScheduler is trying to pick.\n\t\t\t// We also don't care if we throw due to failing the interactive check, because then we'll\n\t\t\t// just appear to never get the task.\n\t\t\tthis.agentScheduler.pick(this.taskId, async () => {}).catch(() => {});\n\t\t\tthis.subscribed = true;\n\t\t}\n\t}\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/agent-scheduler",
3
- "version": "2.53.0",
3
+ "version": "2.60.0",
4
4
  "description": "Built in runtime object for distributing agents across instances of a container",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -47,27 +47,27 @@
47
47
  "main": "lib/index.js",
48
48
  "types": "lib/public.d.ts",
49
49
  "dependencies": {
50
- "@fluid-internal/client-utils": "~2.53.0",
51
- "@fluidframework/container-definitions": "~2.53.0",
52
- "@fluidframework/core-interfaces": "~2.53.0",
53
- "@fluidframework/core-utils": "~2.53.0",
54
- "@fluidframework/datastore": "~2.53.0",
55
- "@fluidframework/datastore-definitions": "~2.53.0",
56
- "@fluidframework/map": "~2.53.0",
57
- "@fluidframework/register-collection": "~2.53.0",
58
- "@fluidframework/runtime-definitions": "~2.53.0",
59
- "@fluidframework/runtime-utils": "~2.53.0",
60
- "@fluidframework/telemetry-utils": "~2.53.0",
50
+ "@fluid-internal/client-utils": "~2.60.0",
51
+ "@fluidframework/container-definitions": "~2.60.0",
52
+ "@fluidframework/core-interfaces": "~2.60.0",
53
+ "@fluidframework/core-utils": "~2.60.0",
54
+ "@fluidframework/datastore": "~2.60.0",
55
+ "@fluidframework/datastore-definitions": "~2.60.0",
56
+ "@fluidframework/map": "~2.60.0",
57
+ "@fluidframework/register-collection": "~2.60.0",
58
+ "@fluidframework/runtime-definitions": "~2.60.0",
59
+ "@fluidframework/runtime-utils": "~2.60.0",
60
+ "@fluidframework/telemetry-utils": "~2.60.0",
61
61
  "uuid": "^11.1.0"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@arethetypeswrong/cli": "^0.17.1",
65
65
  "@biomejs/biome": "~1.9.3",
66
66
  "@fluid-tools/build-cli": "^0.57.0",
67
- "@fluidframework/agent-scheduler-previous": "npm:@fluidframework/agent-scheduler@2.52.0",
67
+ "@fluidframework/agent-scheduler-previous": "npm:@fluidframework/agent-scheduler@2.53.0",
68
68
  "@fluidframework/build-common": "^2.0.3",
69
69
  "@fluidframework/build-tools": "^0.57.0",
70
- "@fluidframework/eslint-config-fluid": "^5.7.4",
70
+ "@fluidframework/eslint-config-fluid": "^6.0.0",
71
71
  "@microsoft/api-extractor": "7.52.8",
72
72
  "@types/node": "^18.19.0",
73
73
  "concurrently": "^8.2.1",
package/src/agent.ts CHANGED
@@ -7,13 +7,13 @@ import type { IEvent, IEventProvider, IFluidLoadable } from "@fluidframework/cor
7
7
 
8
8
  /**
9
9
  * @legacy
10
- * @alpha
10
+ * @beta
11
11
  */
12
12
  export const IAgentScheduler: keyof IProvideAgentScheduler = "IAgentScheduler";
13
13
 
14
14
  /**
15
15
  * @legacy
16
- * @alpha
16
+ * @beta
17
17
  */
18
18
  export interface IProvideAgentScheduler {
19
19
  readonly IAgentScheduler: IAgentScheduler;
@@ -22,7 +22,7 @@ export interface IProvideAgentScheduler {
22
22
  /**
23
23
  * Events emitted by {@link (IAgentScheduler:interface)}.
24
24
  * @legacy
25
- * @alpha
25
+ * @beta
26
26
  */
27
27
  export interface IAgentSchedulerEvents extends IEvent {
28
28
  /**
@@ -48,7 +48,7 @@ export interface IAgentSchedulerEvents extends IEvent {
48
48
  /**
49
49
  * Agent scheduler distributes a set of tasks/variables across connected clients.
50
50
  * @legacy
51
- * @alpha
51
+ * @beta
52
52
  */
53
53
  export interface IAgentScheduler
54
54
  extends IProvideAgentScheduler,
package/src/scheduler.ts CHANGED
@@ -472,7 +472,7 @@ class AgentSchedulerRuntime extends FluidDataStoreRuntime {
472
472
 
473
473
  /**
474
474
  * @legacy
475
- * @alpha
475
+ * @beta
476
476
  */
477
477
  export class AgentSchedulerFactory implements IFluidDataStoreFactory {
478
478
  public static readonly type = "_scheduler";
@@ -11,7 +11,7 @@ import type { IAgentScheduler } from "./agent.js";
11
11
  /**
12
12
  * Events emitted by {@link TaskSubscription}.
13
13
  * @legacy
14
- * @alpha
14
+ * @beta
15
15
  */
16
16
  export interface ITaskSubscriptionEvents extends IEvent {
17
17
  (event: "gotTask" | "lostTask", listener: () => void);
@@ -20,7 +20,7 @@ export interface ITaskSubscriptionEvents extends IEvent {
20
20
  /**
21
21
  * TaskSubscription works with an AgentScheduler to make it easier to monitor a specific task ownership.
22
22
  * @legacy
23
- * @alpha
23
+ * @beta
24
24
  */
25
25
  export class TaskSubscription extends TypedEventEmitter<ITaskSubscriptionEvents> {
26
26
  private subscribed: boolean = false;