@fluid-experimental/data-objects 1.2.1 → 2.0.0-internal.1.0.0.81601

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.
Files changed (39) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/{lib/signalManager → dist/signaler}/index.d.ts +1 -1
  6. package/dist/signaler/index.d.ts.map +1 -0
  7. package/dist/{signalManager → signaler}/index.js +1 -1
  8. package/dist/signaler/index.js.map +1 -0
  9. package/dist/{signalManager/signalManager.d.ts → signaler/signaler.d.ts} +6 -42
  10. package/dist/signaler/signaler.d.ts.map +1 -0
  11. package/dist/{signalManager/signalManager.js → signaler/signaler.js} +25 -28
  12. package/dist/signaler/signaler.js.map +1 -0
  13. package/lib/index.d.ts +1 -1
  14. package/lib/index.d.ts.map +1 -1
  15. package/lib/index.js +1 -1
  16. package/lib/index.js.map +1 -1
  17. package/lib/signaler/index.d.ts +6 -0
  18. package/lib/signaler/index.d.ts.map +1 -0
  19. package/lib/{signalManager → signaler}/index.js +1 -1
  20. package/lib/signaler/index.js.map +1 -0
  21. package/lib/{signalManager/signalManager.d.ts → signaler/signaler.d.ts} +6 -42
  22. package/lib/signaler/signaler.d.ts.map +1 -0
  23. package/lib/{signalManager/signalManager.js → signaler/signaler.js} +25 -28
  24. package/lib/signaler/signaler.js.map +1 -0
  25. package/package.json +5 -5
  26. package/src/index.ts +1 -1
  27. package/src/signaler/README.md +76 -0
  28. package/src/{signalManager → signaler}/index.ts +1 -1
  29. package/src/{signalManager/signalManager.ts → signaler/signaler.ts} +27 -30
  30. package/dist/signalManager/index.d.ts +0 -6
  31. package/dist/signalManager/index.d.ts.map +0 -1
  32. package/dist/signalManager/index.js.map +0 -1
  33. package/dist/signalManager/signalManager.d.ts.map +0 -1
  34. package/dist/signalManager/signalManager.js.map +0 -1
  35. package/lib/signalManager/index.d.ts.map +0 -1
  36. package/lib/signalManager/index.js.map +0 -1
  37. package/lib/signalManager/signalManager.d.ts.map +0 -1
  38. package/lib/signalManager/signalManager.js.map +0 -1
  39. package/src/signalManager/README.md +0 -55
package/dist/index.d.ts CHANGED
@@ -2,5 +2,5 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- export * from "./signalManager";
5
+ export * from "./signaler";
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -2,5 +2,5 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- export * from "./signalManager";
5
+ export * from "./signaler";
6
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,iBAAiB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from \"./signalManager\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,YAAY,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from \"./signaler\";\n"]}
@@ -2,5 +2,5 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- export * from "./signalManager";
5
+ export * from "./signaler";
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/signaler/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,YAAY,CAAC"}
@@ -2,5 +2,5 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- export * from "./signalManager";
5
+ export * from "./signaler";
6
6
  //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/signaler/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,YAAY,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from \"./signaler\";\n"]}
@@ -6,7 +6,6 @@
6
6
  import { EventEmitter } from "events";
7
7
  import { DataObject, DataObjectFactory } from "@fluidframework/aqueduct";
8
8
  import { IErrorEvent } from "@fluidframework/common-definitions";
9
- import { TypedEventEmitter } from "@fluidframework/common-utils";
10
9
  import { Jsonable } from "@fluidframework/datastore-definitions";
11
10
  import { IInboundSignalMessage } from "@fluidframework/runtime-definitions";
12
11
  export declare type SignalListener = (clientId: string, local: boolean, payload: Jsonable) => void;
@@ -49,51 +48,16 @@ export interface IRuntimeSignaler {
49
48
  submitSignal(type: string, content: any): void;
50
49
  }
51
50
  /**
52
- * Note: currently experimental and under development
53
- *
54
- * Helper class to assist common scenarios around working with signals. Signaler wraps a runtime
55
- * object with signaling functionality (e.g. ContainerRuntime or FluidDataStoreRuntime) and can
56
- * then be used in place of the original signaler. It uses a separate internal EventEmitter to
57
- * manage callbacks, and thus will reflect that behavior with regards to callback registration and
58
- * deregistration.
59
- */
60
- export declare class Signaler extends TypedEventEmitter<IErrorEvent> implements ISignaler {
61
- /**
62
- * Object to wrap that can submit and listen to signals
63
- */
64
- private readonly signaler;
65
- private readonly emitter;
66
- private readonly managerId;
67
- constructor(
68
- /**
69
- * Object to wrap that can submit and listen to signals
70
- */
71
- signaler: IRuntimeSignaler,
72
- /**
73
- * Optional id to assign to this manager that will be attached to
74
- * signal names. Useful to avoid collisions if there are multiple
75
- * signal users at the Container level
76
- */
77
- managerId?: string);
78
- private getManagerSignalName;
79
- onSignal(signalName: string, listener: SignalListener): ISignaler;
80
- offSignal(signalName: string, listener: SignalListener): ISignaler;
81
- submitSignal(signalName: string, payload?: Jsonable): void;
82
- }
83
- /**
84
- * Note: currently experimental and under development
85
- *
86
51
  * DataObject implementation of ISignaler for fluid-static plug-and-play. Allows fluid-static
87
- * users to get an ISignaler without a custom DO. Where possible, consumers should instead
88
- * create a Signaler themselves instead of using the DO wrapper to avoid the DO overhead.
52
+ * users to get an ISignaler without a custom DO.
89
53
  */
90
- export declare class SignalManager extends DataObject<{
54
+ export declare class Signaler extends DataObject<{
91
55
  Events: IErrorEvent;
92
56
  }> implements EventEmitter, ISignaler {
93
- private _manager;
94
- private get manager();
57
+ private _signaler;
58
+ private get signaler();
95
59
  static get Name(): string;
96
- static readonly factory: DataObjectFactory<SignalManager, {
60
+ static readonly factory: DataObjectFactory<Signaler, {
97
61
  Events: IErrorEvent;
98
62
  }>;
99
63
  protected hasInitialized(): Promise<void>;
@@ -101,4 +65,4 @@ export declare class SignalManager extends DataObject<{
101
65
  offSignal(signalName: string, listener: SignalListener): ISignaler;
102
66
  submitSignal(signalName: string, payload?: Jsonable): void;
103
67
  }
104
- //# sourceMappingURL=signalManager.d.ts.map
68
+ //# sourceMappingURL=signaler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signaler.d.ts","sourceRoot":"","sources":["../../src/signaler/signaler.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAEjE,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAM5E,oBAAY,cAAc,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,KAAK,IAAI,CAAC;AAE3F;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;IACjE;;;;;;MAME;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;IACnE;;;;OAIG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,OAAE;CACxD;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,OAAE;IACxF,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI,CAAC;CAClD;AA+ED;;;GAGG;AACH,qBAAa,QAAS,SAAQ,UAAU,CAAC;IAAE,MAAM,EAAE,WAAW,CAAC;CAAE,CAAE,YAAW,YAAY,EAAE,SAAS;IACjG,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,KAAK,QAAQ,GAGnB;IAED,WAAkB,IAAI,WAAwC;IAE9D,gBAAuB,OAAO;gBATiB,WAAW;OAcxD;cAEc,cAAc;IASvB,QAAQ,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,cAAc,GACzB,SAAS;IAKL,SAAS,CACZ,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,cAAc,GACzB,SAAS;IAKL,YAAY,CACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,QAAQ;CAIzB"}
@@ -8,13 +8,13 @@ import { assert, TypedEventEmitter } from "@fluidframework/common-utils";
8
8
  /**
9
9
  * Note: currently experimental and under development
10
10
  *
11
- * Helper class to assist common scenarios around working with signals. Signaler wraps a runtime
11
+ * Helper class to assist common scenarios around working with signals. InternalSignaler wraps a runtime
12
12
  * object with signaling functionality (e.g. ContainerRuntime or FluidDataStoreRuntime) and can
13
13
  * then be used in place of the original signaler. It uses a separate internal EventEmitter to
14
14
  * manage callbacks, and thus will reflect that behavior with regards to callback registration and
15
15
  * deregistration.
16
16
  */
17
- export class Signaler extends TypedEventEmitter {
17
+ class InternalSignaler extends TypedEventEmitter {
18
18
  constructor(
19
19
  /**
20
20
  * Object to wrap that can submit and listen to signals
@@ -25,14 +25,14 @@ export class Signaler extends TypedEventEmitter {
25
25
  * signal names. Useful to avoid collisions if there are multiple
26
26
  * signal users at the Container level
27
27
  */
28
- managerId) {
28
+ signalerId) {
29
29
  super();
30
30
  this.signaler = signaler;
31
31
  this.emitter = new EventEmitter();
32
32
  this.emitter.on("error", (error) => {
33
33
  this.emit("error", error);
34
34
  });
35
- this.managerId = managerId ? `#${managerId}` : undefined;
35
+ this.signalerId = signalerId ? `#${signalerId}` : undefined;
36
36
  this.signaler.on("signal", (message, local) => {
37
37
  const clientId = message.clientId;
38
38
  // Only call listeners when the runtime is connected and if the signal has an
@@ -43,58 +43,55 @@ export class Signaler extends TypedEventEmitter {
43
43
  }
44
44
  });
45
45
  }
46
- getManagerSignalName(signalName) {
47
- return this.managerId ? `${signalName}${this.managerId}` : signalName;
46
+ getSignalerSignalName(signalName) {
47
+ return this.signalerId ? `${signalName}${this.signalerId}` : signalName;
48
48
  }
49
49
  // ISignaler methods
50
50
  onSignal(signalName, listener) {
51
- const managerSignalName = this.getManagerSignalName(signalName);
52
- this.emitter.on(managerSignalName, listener);
51
+ const signalerSignalName = this.getSignalerSignalName(signalName);
52
+ this.emitter.on(signalerSignalName, listener);
53
53
  return this;
54
54
  }
55
55
  offSignal(signalName, listener) {
56
- const managerSignalName = this.getManagerSignalName(signalName);
57
- this.emitter.off(managerSignalName, listener);
56
+ const signalerSignalName = this.getSignalerSignalName(signalName);
57
+ this.emitter.off(signalerSignalName, listener);
58
58
  return this;
59
59
  }
60
60
  submitSignal(signalName, payload) {
61
- const managerSignalName = this.getManagerSignalName(signalName);
61
+ const signalerSignalName = this.getSignalerSignalName(signalName);
62
62
  if (this.signaler.connected) {
63
- this.signaler.submitSignal(managerSignalName, payload);
63
+ this.signaler.submitSignal(signalerSignalName, payload);
64
64
  }
65
65
  }
66
66
  }
67
67
  /**
68
- * Note: currently experimental and under development
69
- *
70
68
  * DataObject implementation of ISignaler for fluid-static plug-and-play. Allows fluid-static
71
- * users to get an ISignaler without a custom DO. Where possible, consumers should instead
72
- * create a Signaler themselves instead of using the DO wrapper to avoid the DO overhead.
69
+ * users to get an ISignaler without a custom DO.
73
70
  */
74
- export class SignalManager extends DataObject {
75
- get manager() {
76
- assert(this._manager !== undefined, 0x24b /* "internal signaler should be defined" */);
77
- return this._manager;
71
+ export class Signaler extends DataObject {
72
+ get signaler() {
73
+ assert(this._signaler !== undefined, 0x24b /* "internal signaler should be defined" */);
74
+ return this._signaler;
78
75
  }
79
- static get Name() { return "@fluid-example/signal-manager"; }
76
+ static get Name() { return "@fluid-example/signaler"; }
80
77
  async hasInitialized() {
81
- this._manager = new Signaler(this.runtime);
82
- this.manager.on("error", (error) => {
78
+ this._signaler = new InternalSignaler(this.runtime);
79
+ this.signaler.on("error", (error) => {
83
80
  this.emit("error", error);
84
81
  });
85
82
  }
86
83
  // ISignaler methods Note these are all passthroughs
87
84
  onSignal(signalName, listener) {
88
- this.manager.onSignal(signalName, listener);
85
+ this.signaler.onSignal(signalName, listener);
89
86
  return this;
90
87
  }
91
88
  offSignal(signalName, listener) {
92
- this.manager.offSignal(signalName, listener);
89
+ this.signaler.offSignal(signalName, listener);
93
90
  return this;
94
91
  }
95
92
  submitSignal(signalName, payload) {
96
- this.manager.submitSignal(signalName, payload);
93
+ this.signaler.submitSignal(signalName, payload);
97
94
  }
98
95
  }
99
- SignalManager.factory = new DataObjectFactory(SignalManager.Name, SignalManager, [], {});
100
- //# sourceMappingURL=signalManager.js.map
96
+ Signaler.factory = new DataObjectFactory(Signaler.Name, Signaler, [], {});
97
+ //# sourceMappingURL=signaler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signaler.js","sourceRoot":"","sources":["../../src/signaler/signaler.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 { EventEmitter } from \"events\";\nimport { DataObject, DataObjectFactory } from \"@fluidframework/aqueduct\";\nimport { IErrorEvent } from \"@fluidframework/common-definitions\";\nimport { assert, TypedEventEmitter } from \"@fluidframework/common-utils\";\nimport { Jsonable } from \"@fluidframework/datastore-definitions\";\nimport { IInboundSignalMessage } from \"@fluidframework/runtime-definitions\";\n\n// TODO:\n// add way to mark with current sequence number for ordering signals relative to ops\n// throttling and batching\n\nexport type SignalListener = (clientId: string, local: boolean, payload: Jsonable) => void;\n\n/**\n * ISignaler defines an interface for working with signals that is similar to the more common\n * eventing patterns of EventEmitter. In addition to sending and responding to signals, it\n * provides explicit methods around signal requests to other connected clients.\n */\nexport interface ISignaler {\n /**\n * Adds a listener for the specified signal. It behaves in the same way as EventEmitter's `on`\n * method regarding multiple registrations, callback order, etc.\n * @param signalName - The name of the signal\n * @param listener - The callback signal handler to add\n * @returns This ISignaler\n */\n onSignal(signalName: string, listener: SignalListener): ISignaler;\n /**\n * Remove a listener for the specified signal. It behaves in the same way as EventEmitter's\n * `off` method regarding multiple registrations, removal order, etc.\n * @param signalName - The name of the signal\n * @param listener - The callback signal handler to remove\n * @returns This ISignaler\n */\n offSignal(signalName: string, listener: SignalListener): ISignaler;\n /**\n * Send a signal with payload to its connected listeners.\n * @param signalName - The name of the signal\n * @param payload - The data to send with the signal\n */\n submitSignal(signalName: string, payload?: Jsonable);\n}\n\n/**\n * Duck type of something that provides the expected signalling functionality:\n * A way to verify we can signal, a way to send a signal, and a way to listen for incoming signals\n */\nexport interface IRuntimeSignaler {\n connected: boolean;\n on(event: \"signal\", listener: (message: IInboundSignalMessage, local: boolean) => void);\n submitSignal(type: string, content: any): void;\n}\n\n/**\n * Note: currently experimental and under development\n *\n * Helper class to assist common scenarios around working with signals. InternalSignaler wraps a runtime\n * object with signaling functionality (e.g. ContainerRuntime or FluidDataStoreRuntime) and can\n * then be used in place of the original signaler. It uses a separate internal EventEmitter to\n * manage callbacks, and thus will reflect that behavior with regards to callback registration and\n * deregistration.\n */\n class InternalSignaler extends TypedEventEmitter<IErrorEvent> implements ISignaler {\n private readonly emitter = new EventEmitter();\n\n private readonly signalerId: string | undefined;\n\n constructor(\n /**\n * Object to wrap that can submit and listen to signals\n */\n private readonly signaler: IRuntimeSignaler,\n /**\n * Optional id to assign to this manager that will be attached to\n * signal names. Useful to avoid collisions if there are multiple\n * signal users at the Container level\n */\n signalerId?: string,\n ) {\n super();\n this.emitter.on(\"error\", (error) => {\n this.emit(\"error\", error);\n });\n this.signalerId = signalerId ? `#${signalerId}` : undefined;\n this.signaler.on(\"signal\", (message: IInboundSignalMessage, local: boolean) => {\n const clientId = message.clientId;\n // Only call listeners when the runtime is connected and if the signal has an\n // identifiable sender clientId. The listener is responsible for deciding how\n // it wants to handle local/remote signals\n if (this.signaler.connected && clientId !== null) {\n this.emitter.emit(message.type, clientId, local, message.content);\n }\n });\n }\n\n private getSignalerSignalName(signalName: string): string {\n return this.signalerId ? `${signalName}${this.signalerId}` : signalName;\n }\n\n // ISignaler methods\n\n public onSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n const signalerSignalName = this.getSignalerSignalName(signalName);\n this.emitter.on(signalerSignalName, listener);\n return this;\n }\n\n public offSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n const signalerSignalName = this.getSignalerSignalName(signalName);\n this.emitter.off(signalerSignalName, listener);\n return this;\n }\n\n public submitSignal(\n signalName: string,\n payload?: Jsonable,\n ) {\n const signalerSignalName = this.getSignalerSignalName(signalName);\n if (this.signaler.connected) {\n this.signaler.submitSignal(signalerSignalName, payload);\n }\n }\n}\n\n/**\n * DataObject implementation of ISignaler for fluid-static plug-and-play. Allows fluid-static\n * users to get an ISignaler without a custom DO.\n */\nexport class Signaler extends DataObject<{ Events: IErrorEvent; }> implements EventEmitter, ISignaler {\n private _signaler: InternalSignaler | undefined;\n private get signaler(): InternalSignaler {\n assert(this._signaler !== undefined, 0x24b /* \"internal signaler should be defined\" */);\n return this._signaler;\n }\n\n public static get Name() { return \"@fluid-example/signaler\"; }\n\n public static readonly factory = new DataObjectFactory(\n Signaler.Name,\n Signaler,\n [],\n {},\n );\n\n protected async hasInitialized() {\n this._signaler = new InternalSignaler(this.runtime);\n this.signaler.on(\"error\", (error) => {\n this.emit(\"error\", error);\n });\n }\n\n // ISignaler methods Note these are all passthroughs\n\n public onSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n this.signaler.onSignal(signalName, listener);\n return this;\n }\n\n public offSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n this.signaler.offSignal(signalName, listener);\n return this;\n }\n\n public submitSignal(\n signalName: string,\n payload?: Jsonable,\n ) {\n this.signaler.submitSignal(signalName, payload);\n }\n}\n"]}
package/lib/index.d.ts CHANGED
@@ -2,5 +2,5 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- export * from "./signalManager";
5
+ export * from "./signaler";
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,YAAY,CAAC"}
package/lib/index.js CHANGED
@@ -2,5 +2,5 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- export * from "./signalManager";
5
+ export * from "./signaler";
6
6
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,iBAAiB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from \"./signalManager\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,YAAY,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from \"./signaler\";\n"]}
@@ -0,0 +1,6 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ export * from "./signaler";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/signaler/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,YAAY,CAAC"}
@@ -2,5 +2,5 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- export * from "./signalManager";
5
+ export * from "./signaler";
6
6
  //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/signaler/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,YAAY,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from \"./signaler\";\n"]}
@@ -6,7 +6,6 @@
6
6
  import { EventEmitter } from "events";
7
7
  import { DataObject, DataObjectFactory } from "@fluidframework/aqueduct";
8
8
  import { IErrorEvent } from "@fluidframework/common-definitions";
9
- import { TypedEventEmitter } from "@fluidframework/common-utils";
10
9
  import { Jsonable } from "@fluidframework/datastore-definitions";
11
10
  import { IInboundSignalMessage } from "@fluidframework/runtime-definitions";
12
11
  export declare type SignalListener = (clientId: string, local: boolean, payload: Jsonable) => void;
@@ -49,51 +48,16 @@ export interface IRuntimeSignaler {
49
48
  submitSignal(type: string, content: any): void;
50
49
  }
51
50
  /**
52
- * Note: currently experimental and under development
53
- *
54
- * Helper class to assist common scenarios around working with signals. Signaler wraps a runtime
55
- * object with signaling functionality (e.g. ContainerRuntime or FluidDataStoreRuntime) and can
56
- * then be used in place of the original signaler. It uses a separate internal EventEmitter to
57
- * manage callbacks, and thus will reflect that behavior with regards to callback registration and
58
- * deregistration.
59
- */
60
- export declare class Signaler extends TypedEventEmitter<IErrorEvent> implements ISignaler {
61
- /**
62
- * Object to wrap that can submit and listen to signals
63
- */
64
- private readonly signaler;
65
- private readonly emitter;
66
- private readonly managerId;
67
- constructor(
68
- /**
69
- * Object to wrap that can submit and listen to signals
70
- */
71
- signaler: IRuntimeSignaler,
72
- /**
73
- * Optional id to assign to this manager that will be attached to
74
- * signal names. Useful to avoid collisions if there are multiple
75
- * signal users at the Container level
76
- */
77
- managerId?: string);
78
- private getManagerSignalName;
79
- onSignal(signalName: string, listener: SignalListener): ISignaler;
80
- offSignal(signalName: string, listener: SignalListener): ISignaler;
81
- submitSignal(signalName: string, payload?: Jsonable): void;
82
- }
83
- /**
84
- * Note: currently experimental and under development
85
- *
86
51
  * DataObject implementation of ISignaler for fluid-static plug-and-play. Allows fluid-static
87
- * users to get an ISignaler without a custom DO. Where possible, consumers should instead
88
- * create a Signaler themselves instead of using the DO wrapper to avoid the DO overhead.
52
+ * users to get an ISignaler without a custom DO.
89
53
  */
90
- export declare class SignalManager extends DataObject<{
54
+ export declare class Signaler extends DataObject<{
91
55
  Events: IErrorEvent;
92
56
  }> implements EventEmitter, ISignaler {
93
- private _manager;
94
- private get manager();
57
+ private _signaler;
58
+ private get signaler();
95
59
  static get Name(): string;
96
- static readonly factory: DataObjectFactory<SignalManager, {
60
+ static readonly factory: DataObjectFactory<Signaler, {
97
61
  Events: IErrorEvent;
98
62
  }>;
99
63
  protected hasInitialized(): Promise<void>;
@@ -101,4 +65,4 @@ export declare class SignalManager extends DataObject<{
101
65
  offSignal(signalName: string, listener: SignalListener): ISignaler;
102
66
  submitSignal(signalName: string, payload?: Jsonable): void;
103
67
  }
104
- //# sourceMappingURL=signalManager.d.ts.map
68
+ //# sourceMappingURL=signaler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signaler.d.ts","sourceRoot":"","sources":["../../src/signaler/signaler.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAEjE,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAM5E,oBAAY,cAAc,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,KAAK,IAAI,CAAC;AAE3F;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;IACjE;;;;;;MAME;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;IACnE;;;;OAIG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,OAAE;CACxD;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,OAAE;IACxF,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI,CAAC;CAClD;AA+ED;;;GAGG;AACH,qBAAa,QAAS,SAAQ,UAAU,CAAC;IAAE,MAAM,EAAE,WAAW,CAAC;CAAE,CAAE,YAAW,YAAY,EAAE,SAAS;IACjG,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,KAAK,QAAQ,GAGnB;IAED,WAAkB,IAAI,WAAwC;IAE9D,gBAAuB,OAAO;gBATiB,WAAW;OAcxD;cAEc,cAAc;IASvB,QAAQ,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,cAAc,GACzB,SAAS;IAKL,SAAS,CACZ,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,cAAc,GACzB,SAAS;IAKL,YAAY,CACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,QAAQ;CAIzB"}
@@ -8,13 +8,13 @@ import { assert, TypedEventEmitter } from "@fluidframework/common-utils";
8
8
  /**
9
9
  * Note: currently experimental and under development
10
10
  *
11
- * Helper class to assist common scenarios around working with signals. Signaler wraps a runtime
11
+ * Helper class to assist common scenarios around working with signals. InternalSignaler wraps a runtime
12
12
  * object with signaling functionality (e.g. ContainerRuntime or FluidDataStoreRuntime) and can
13
13
  * then be used in place of the original signaler. It uses a separate internal EventEmitter to
14
14
  * manage callbacks, and thus will reflect that behavior with regards to callback registration and
15
15
  * deregistration.
16
16
  */
17
- export class Signaler extends TypedEventEmitter {
17
+ class InternalSignaler extends TypedEventEmitter {
18
18
  constructor(
19
19
  /**
20
20
  * Object to wrap that can submit and listen to signals
@@ -25,14 +25,14 @@ export class Signaler extends TypedEventEmitter {
25
25
  * signal names. Useful to avoid collisions if there are multiple
26
26
  * signal users at the Container level
27
27
  */
28
- managerId) {
28
+ signalerId) {
29
29
  super();
30
30
  this.signaler = signaler;
31
31
  this.emitter = new EventEmitter();
32
32
  this.emitter.on("error", (error) => {
33
33
  this.emit("error", error);
34
34
  });
35
- this.managerId = managerId ? `#${managerId}` : undefined;
35
+ this.signalerId = signalerId ? `#${signalerId}` : undefined;
36
36
  this.signaler.on("signal", (message, local) => {
37
37
  const clientId = message.clientId;
38
38
  // Only call listeners when the runtime is connected and if the signal has an
@@ -43,58 +43,55 @@ export class Signaler extends TypedEventEmitter {
43
43
  }
44
44
  });
45
45
  }
46
- getManagerSignalName(signalName) {
47
- return this.managerId ? `${signalName}${this.managerId}` : signalName;
46
+ getSignalerSignalName(signalName) {
47
+ return this.signalerId ? `${signalName}${this.signalerId}` : signalName;
48
48
  }
49
49
  // ISignaler methods
50
50
  onSignal(signalName, listener) {
51
- const managerSignalName = this.getManagerSignalName(signalName);
52
- this.emitter.on(managerSignalName, listener);
51
+ const signalerSignalName = this.getSignalerSignalName(signalName);
52
+ this.emitter.on(signalerSignalName, listener);
53
53
  return this;
54
54
  }
55
55
  offSignal(signalName, listener) {
56
- const managerSignalName = this.getManagerSignalName(signalName);
57
- this.emitter.off(managerSignalName, listener);
56
+ const signalerSignalName = this.getSignalerSignalName(signalName);
57
+ this.emitter.off(signalerSignalName, listener);
58
58
  return this;
59
59
  }
60
60
  submitSignal(signalName, payload) {
61
- const managerSignalName = this.getManagerSignalName(signalName);
61
+ const signalerSignalName = this.getSignalerSignalName(signalName);
62
62
  if (this.signaler.connected) {
63
- this.signaler.submitSignal(managerSignalName, payload);
63
+ this.signaler.submitSignal(signalerSignalName, payload);
64
64
  }
65
65
  }
66
66
  }
67
67
  /**
68
- * Note: currently experimental and under development
69
- *
70
68
  * DataObject implementation of ISignaler for fluid-static plug-and-play. Allows fluid-static
71
- * users to get an ISignaler without a custom DO. Where possible, consumers should instead
72
- * create a Signaler themselves instead of using the DO wrapper to avoid the DO overhead.
69
+ * users to get an ISignaler without a custom DO.
73
70
  */
74
- export class SignalManager extends DataObject {
75
- get manager() {
76
- assert(this._manager !== undefined, 0x24b /* "internal signaler should be defined" */);
77
- return this._manager;
71
+ export class Signaler extends DataObject {
72
+ get signaler() {
73
+ assert(this._signaler !== undefined, 0x24b /* "internal signaler should be defined" */);
74
+ return this._signaler;
78
75
  }
79
- static get Name() { return "@fluid-example/signal-manager"; }
76
+ static get Name() { return "@fluid-example/signaler"; }
80
77
  async hasInitialized() {
81
- this._manager = new Signaler(this.runtime);
82
- this.manager.on("error", (error) => {
78
+ this._signaler = new InternalSignaler(this.runtime);
79
+ this.signaler.on("error", (error) => {
83
80
  this.emit("error", error);
84
81
  });
85
82
  }
86
83
  // ISignaler methods Note these are all passthroughs
87
84
  onSignal(signalName, listener) {
88
- this.manager.onSignal(signalName, listener);
85
+ this.signaler.onSignal(signalName, listener);
89
86
  return this;
90
87
  }
91
88
  offSignal(signalName, listener) {
92
- this.manager.offSignal(signalName, listener);
89
+ this.signaler.offSignal(signalName, listener);
93
90
  return this;
94
91
  }
95
92
  submitSignal(signalName, payload) {
96
- this.manager.submitSignal(signalName, payload);
93
+ this.signaler.submitSignal(signalName, payload);
97
94
  }
98
95
  }
99
- SignalManager.factory = new DataObjectFactory(SignalManager.Name, SignalManager, [], {});
100
- //# sourceMappingURL=signalManager.js.map
96
+ Signaler.factory = new DataObjectFactory(Signaler.Name, Signaler, [], {});
97
+ //# sourceMappingURL=signaler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signaler.js","sourceRoot":"","sources":["../../src/signaler/signaler.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 { EventEmitter } from \"events\";\nimport { DataObject, DataObjectFactory } from \"@fluidframework/aqueduct\";\nimport { IErrorEvent } from \"@fluidframework/common-definitions\";\nimport { assert, TypedEventEmitter } from \"@fluidframework/common-utils\";\nimport { Jsonable } from \"@fluidframework/datastore-definitions\";\nimport { IInboundSignalMessage } from \"@fluidframework/runtime-definitions\";\n\n// TODO:\n// add way to mark with current sequence number for ordering signals relative to ops\n// throttling and batching\n\nexport type SignalListener = (clientId: string, local: boolean, payload: Jsonable) => void;\n\n/**\n * ISignaler defines an interface for working with signals that is similar to the more common\n * eventing patterns of EventEmitter. In addition to sending and responding to signals, it\n * provides explicit methods around signal requests to other connected clients.\n */\nexport interface ISignaler {\n /**\n * Adds a listener for the specified signal. It behaves in the same way as EventEmitter's `on`\n * method regarding multiple registrations, callback order, etc.\n * @param signalName - The name of the signal\n * @param listener - The callback signal handler to add\n * @returns This ISignaler\n */\n onSignal(signalName: string, listener: SignalListener): ISignaler;\n /**\n * Remove a listener for the specified signal. It behaves in the same way as EventEmitter's\n * `off` method regarding multiple registrations, removal order, etc.\n * @param signalName - The name of the signal\n * @param listener - The callback signal handler to remove\n * @returns This ISignaler\n */\n offSignal(signalName: string, listener: SignalListener): ISignaler;\n /**\n * Send a signal with payload to its connected listeners.\n * @param signalName - The name of the signal\n * @param payload - The data to send with the signal\n */\n submitSignal(signalName: string, payload?: Jsonable);\n}\n\n/**\n * Duck type of something that provides the expected signalling functionality:\n * A way to verify we can signal, a way to send a signal, and a way to listen for incoming signals\n */\nexport interface IRuntimeSignaler {\n connected: boolean;\n on(event: \"signal\", listener: (message: IInboundSignalMessage, local: boolean) => void);\n submitSignal(type: string, content: any): void;\n}\n\n/**\n * Note: currently experimental and under development\n *\n * Helper class to assist common scenarios around working with signals. InternalSignaler wraps a runtime\n * object with signaling functionality (e.g. ContainerRuntime or FluidDataStoreRuntime) and can\n * then be used in place of the original signaler. It uses a separate internal EventEmitter to\n * manage callbacks, and thus will reflect that behavior with regards to callback registration and\n * deregistration.\n */\n class InternalSignaler extends TypedEventEmitter<IErrorEvent> implements ISignaler {\n private readonly emitter = new EventEmitter();\n\n private readonly signalerId: string | undefined;\n\n constructor(\n /**\n * Object to wrap that can submit and listen to signals\n */\n private readonly signaler: IRuntimeSignaler,\n /**\n * Optional id to assign to this manager that will be attached to\n * signal names. Useful to avoid collisions if there are multiple\n * signal users at the Container level\n */\n signalerId?: string,\n ) {\n super();\n this.emitter.on(\"error\", (error) => {\n this.emit(\"error\", error);\n });\n this.signalerId = signalerId ? `#${signalerId}` : undefined;\n this.signaler.on(\"signal\", (message: IInboundSignalMessage, local: boolean) => {\n const clientId = message.clientId;\n // Only call listeners when the runtime is connected and if the signal has an\n // identifiable sender clientId. The listener is responsible for deciding how\n // it wants to handle local/remote signals\n if (this.signaler.connected && clientId !== null) {\n this.emitter.emit(message.type, clientId, local, message.content);\n }\n });\n }\n\n private getSignalerSignalName(signalName: string): string {\n return this.signalerId ? `${signalName}${this.signalerId}` : signalName;\n }\n\n // ISignaler methods\n\n public onSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n const signalerSignalName = this.getSignalerSignalName(signalName);\n this.emitter.on(signalerSignalName, listener);\n return this;\n }\n\n public offSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n const signalerSignalName = this.getSignalerSignalName(signalName);\n this.emitter.off(signalerSignalName, listener);\n return this;\n }\n\n public submitSignal(\n signalName: string,\n payload?: Jsonable,\n ) {\n const signalerSignalName = this.getSignalerSignalName(signalName);\n if (this.signaler.connected) {\n this.signaler.submitSignal(signalerSignalName, payload);\n }\n }\n}\n\n/**\n * DataObject implementation of ISignaler for fluid-static plug-and-play. Allows fluid-static\n * users to get an ISignaler without a custom DO.\n */\nexport class Signaler extends DataObject<{ Events: IErrorEvent; }> implements EventEmitter, ISignaler {\n private _signaler: InternalSignaler | undefined;\n private get signaler(): InternalSignaler {\n assert(this._signaler !== undefined, 0x24b /* \"internal signaler should be defined\" */);\n return this._signaler;\n }\n\n public static get Name() { return \"@fluid-example/signaler\"; }\n\n public static readonly factory = new DataObjectFactory(\n Signaler.Name,\n Signaler,\n [],\n {},\n );\n\n protected async hasInitialized() {\n this._signaler = new InternalSignaler(this.runtime);\n this.signaler.on(\"error\", (error) => {\n this.emit(\"error\", error);\n });\n }\n\n // ISignaler methods Note these are all passthroughs\n\n public onSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n this.signaler.onSignal(signalName, listener);\n return this;\n }\n\n public offSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n this.signaler.offSignal(signalName, listener);\n return this;\n }\n\n public submitSignal(\n signalName: string,\n payload?: Jsonable,\n ) {\n this.signaler.submitSignal(signalName, payload);\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-experimental/data-objects",
3
- "version": "1.2.1",
3
+ "version": "2.0.0-internal.1.0.0.81601",
4
4
  "description": "A collection of ready to use Fluid Data Objects",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -31,12 +31,12 @@
31
31
  "tsfmt:fix": "tsfmt --replace"
32
32
  },
33
33
  "dependencies": {
34
- "@fluidframework/aqueduct": "^1.2.1",
34
+ "@fluidframework/aqueduct": "2.0.0-internal.1.0.0.81601",
35
35
  "@fluidframework/common-definitions": "^0.20.1",
36
36
  "@fluidframework/common-utils": "^0.32.1",
37
- "@fluidframework/datastore-definitions": "^1.2.1",
38
- "@fluidframework/map": "^1.2.1",
39
- "@fluidframework/runtime-definitions": "^1.2.1"
37
+ "@fluidframework/datastore-definitions": "2.0.0-internal.1.0.0.81601",
38
+ "@fluidframework/map": "2.0.0-internal.1.0.0.81601",
39
+ "@fluidframework/runtime-definitions": "2.0.0-internal.1.0.0.81601"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@fluidframework/build-common": "^0.24.0",
package/src/index.ts CHANGED
@@ -3,4 +3,4 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- export * from "./signalManager";
6
+ export * from "./signaler";
@@ -0,0 +1,76 @@
1
+ # Signaler
2
+ The `Signaler` is a DataObject that can be used to communicate transient data via signals. Transient data refers to impermanent information that is not persisted with the container.
3
+
4
+ ## Usage
5
+ User presence scenarios are well-suited for `Signaler`, as users are required to tell other users their own information and their past data is mostly irrelavant. Using `Signaler` over other distributed data structures in these scenarios is beneficial, as its usage does not result in the storage of data that is not useful in the long-term.
6
+
7
+ ### Creation
8
+ Just like with DDSes, you can include `Signaler` as a shared object you would like to load in your `FluidContainer` schema.
9
+
10
+ Here is a look at how you would go about loading `Signaler` as part of the initial objects of the container:
11
+
12
+ ```typescript
13
+ const containerSchema: ContainerSchema = {
14
+ initialObjects: {
15
+ signaler: Signaler,
16
+ },
17
+ };
18
+
19
+ const { container, services } = await client.createContainer(containerSchema);
20
+
21
+ const signaler = container.initialObjects.signaler as Signaler;
22
+ ```
23
+
24
+ `signaler` can then be directly used in your Fluid application!
25
+
26
+ For more information on using `ContainerSchema` to create objects please see [Data modeling](https://fluidframework.com/docs/build/data-modeling/).
27
+
28
+ ## API
29
+ `Signaler` provides a few simple methods to send signals and add/remove listeners to specific signals as well:
30
+ - `submitSignal(signalName: string, payload?: Jsonable)` - Sends a signal with a payload to its connected listeners
31
+ - `onSignal(signalName: string, listener: SignalListener)` - Adds a listener for the specified signal. Same behavior as EventEmitter's `on` method.
32
+ - `offSignal(signalName: string, listener: SignalListener)` - Removes a listener for the specified signal. Same behavior as EventEmitter's `off` method.
33
+
34
+ ## Common Patterns
35
+ ### Signal Request
36
+ When a client joins a collaboration session, they may need to receive pertinent information immediately after connecting the container. To support this, they can request a specific signal be sent to them from other connected clients within the application. For example, in the [PresenceTracker](https://github.com/microsoft/FluidFramework/tree/main/examples/data-objects/presence-tracker) we define a "focusRequest" signal type that a newly joining client uses to request the focus-state of each currently connected client:
37
+
38
+ ```typescript
39
+ private static readonly focusRequestType = "focusRequest";
40
+ ```
41
+
42
+ ```typescript
43
+ container.on("connected", () => {
44
+ this.signaler.submitSignal(FocusTracker.focusRequestType);
45
+ });
46
+ ```
47
+
48
+ The connected clients are listening to this focus request signal, and they respond with their current focus state:
49
+
50
+ ```typescript
51
+ this.signaler.onSignal(FocusTracker.focusRequestType, () => {
52
+ this.sendFocusSignal(document.hasFocus());
53
+ });
54
+ ```
55
+ When there are a lot of connected clients, usage of this request pattern can lead to high signal costs incurred from large amounts of signals being submitted all at the same time. While this pattern is helpful when a client is in need of relevant information, to limit signal costs it would be beneficial to examine whether or not the requested data will be quickly avaiable from other events being listened to within the application. The mouse tracking in [PresenceTracker](https://github.com/microsoft/FluidFramework/tree/main/examples/data-objects/presence-tracker) is an example where a newly connecting client is not required to request a signal to receive every current mouse position on the document. Since mouse movements are frequent, the newly connecting client can simply wait to recieve other users mouse positions on their mousemove events.
56
+ ### Grouping Signal Types
57
+
58
+ Rather than submitting multiple signal types in response to one specific event, it is more cost-effective to create one seperate signal type for that particular event and listen to that single signal instead. For example, imagine an application using the `Signal Request` pattern where a newly connected client requests for the color, focus state, and currently selected object of every other connected client on the page. If you submit a signal for each type of data requested, it would look something like this:
59
+
60
+ ```typescript
61
+ container.on("connected", () => {
62
+ this.signaler.submitSignal("colorRequest");
63
+ this.signaler.submitSignal("focusRequest");
64
+ this.signaler.submitSignal("currentlySelectedObjectRequest");
65
+ });
66
+ ```
67
+
68
+ This approach is costly since the amount of signals sent back on request grows linearly with the amount of connected users. So if there are three signals requested as opposed to one, there are 3 times as many total signals being submitted on every connect. To avoid this costly scenario we can group the signal types into one single signal that captures all the required information:
69
+
70
+ ```typescript
71
+ container.on("connected", () => {
72
+ this.signaler.submitSignal("connectRequest");
73
+ });
74
+ ```
75
+
76
+ The idea is that the payload sent back on the `connectRequest` will include all the relevant information the newly connected user needs.
@@ -3,4 +3,4 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- export * from "./signalManager";
6
+ export * from "./signaler";
@@ -59,16 +59,16 @@ export interface IRuntimeSignaler {
59
59
  /**
60
60
  * Note: currently experimental and under development
61
61
  *
62
- * Helper class to assist common scenarios around working with signals. Signaler wraps a runtime
62
+ * Helper class to assist common scenarios around working with signals. InternalSignaler wraps a runtime
63
63
  * object with signaling functionality (e.g. ContainerRuntime or FluidDataStoreRuntime) and can
64
64
  * then be used in place of the original signaler. It uses a separate internal EventEmitter to
65
65
  * manage callbacks, and thus will reflect that behavior with regards to callback registration and
66
66
  * deregistration.
67
67
  */
68
- export class Signaler extends TypedEventEmitter<IErrorEvent> implements ISignaler {
68
+ class InternalSignaler extends TypedEventEmitter<IErrorEvent> implements ISignaler {
69
69
  private readonly emitter = new EventEmitter();
70
70
 
71
- private readonly managerId: string | undefined;
71
+ private readonly signalerId: string | undefined;
72
72
 
73
73
  constructor(
74
74
  /**
@@ -80,13 +80,13 @@ export class Signaler extends TypedEventEmitter<IErrorEvent> implements ISignale
80
80
  * signal names. Useful to avoid collisions if there are multiple
81
81
  * signal users at the Container level
82
82
  */
83
- managerId?: string,
83
+ signalerId?: string,
84
84
  ) {
85
85
  super();
86
86
  this.emitter.on("error", (error) => {
87
87
  this.emit("error", error);
88
88
  });
89
- this.managerId = managerId ? `#${managerId}` : undefined;
89
+ this.signalerId = signalerId ? `#${signalerId}` : undefined;
90
90
  this.signaler.on("signal", (message: IInboundSignalMessage, local: boolean) => {
91
91
  const clientId = message.clientId;
92
92
  // Only call listeners when the runtime is connected and if the signal has an
@@ -98,8 +98,8 @@ export class Signaler extends TypedEventEmitter<IErrorEvent> implements ISignale
98
98
  });
99
99
  }
100
100
 
101
- private getManagerSignalName(signalName: string): string {
102
- return this.managerId ? `${signalName}${this.managerId}` : signalName;
101
+ private getSignalerSignalName(signalName: string): string {
102
+ return this.signalerId ? `${signalName}${this.signalerId}` : signalName;
103
103
  }
104
104
 
105
105
  // ISignaler methods
@@ -108,8 +108,8 @@ export class Signaler extends TypedEventEmitter<IErrorEvent> implements ISignale
108
108
  signalName: string,
109
109
  listener: SignalListener,
110
110
  ): ISignaler {
111
- const managerSignalName = this.getManagerSignalName(signalName);
112
- this.emitter.on(managerSignalName, listener);
111
+ const signalerSignalName = this.getSignalerSignalName(signalName);
112
+ this.emitter.on(signalerSignalName, listener);
113
113
  return this;
114
114
  }
115
115
 
@@ -117,8 +117,8 @@ export class Signaler extends TypedEventEmitter<IErrorEvent> implements ISignale
117
117
  signalName: string,
118
118
  listener: SignalListener,
119
119
  ): ISignaler {
120
- const managerSignalName = this.getManagerSignalName(signalName);
121
- this.emitter.off(managerSignalName, listener);
120
+ const signalerSignalName = this.getSignalerSignalName(signalName);
121
+ this.emitter.off(signalerSignalName, listener);
122
122
  return this;
123
123
  }
124
124
 
@@ -126,39 +126,36 @@ export class Signaler extends TypedEventEmitter<IErrorEvent> implements ISignale
126
126
  signalName: string,
127
127
  payload?: Jsonable,
128
128
  ) {
129
- const managerSignalName = this.getManagerSignalName(signalName);
129
+ const signalerSignalName = this.getSignalerSignalName(signalName);
130
130
  if (this.signaler.connected) {
131
- this.signaler.submitSignal(managerSignalName, payload);
131
+ this.signaler.submitSignal(signalerSignalName, payload);
132
132
  }
133
133
  }
134
134
  }
135
135
 
136
136
  /**
137
- * Note: currently experimental and under development
138
- *
139
137
  * DataObject implementation of ISignaler for fluid-static plug-and-play. Allows fluid-static
140
- * users to get an ISignaler without a custom DO. Where possible, consumers should instead
141
- * create a Signaler themselves instead of using the DO wrapper to avoid the DO overhead.
138
+ * users to get an ISignaler without a custom DO.
142
139
  */
143
- export class SignalManager extends DataObject<{ Events: IErrorEvent; }> implements EventEmitter, ISignaler {
144
- private _manager: Signaler | undefined;
145
- private get manager(): Signaler {
146
- assert(this._manager !== undefined, 0x24b /* "internal signaler should be defined" */);
147
- return this._manager;
140
+ export class Signaler extends DataObject<{ Events: IErrorEvent; }> implements EventEmitter, ISignaler {
141
+ private _signaler: InternalSignaler | undefined;
142
+ private get signaler(): InternalSignaler {
143
+ assert(this._signaler !== undefined, 0x24b /* "internal signaler should be defined" */);
144
+ return this._signaler;
148
145
  }
149
146
 
150
- public static get Name() { return "@fluid-example/signal-manager"; }
147
+ public static get Name() { return "@fluid-example/signaler"; }
151
148
 
152
149
  public static readonly factory = new DataObjectFactory(
153
- SignalManager.Name,
154
- SignalManager,
150
+ Signaler.Name,
151
+ Signaler,
155
152
  [],
156
153
  {},
157
154
  );
158
155
 
159
156
  protected async hasInitialized() {
160
- this._manager = new Signaler(this.runtime);
161
- this.manager.on("error", (error) => {
157
+ this._signaler = new InternalSignaler(this.runtime);
158
+ this.signaler.on("error", (error) => {
162
159
  this.emit("error", error);
163
160
  });
164
161
  }
@@ -169,7 +166,7 @@ export class SignalManager extends DataObject<{ Events: IErrorEvent; }> implemen
169
166
  signalName: string,
170
167
  listener: SignalListener,
171
168
  ): ISignaler {
172
- this.manager.onSignal(signalName, listener);
169
+ this.signaler.onSignal(signalName, listener);
173
170
  return this;
174
171
  }
175
172
 
@@ -177,7 +174,7 @@ export class SignalManager extends DataObject<{ Events: IErrorEvent; }> implemen
177
174
  signalName: string,
178
175
  listener: SignalListener,
179
176
  ): ISignaler {
180
- this.manager.offSignal(signalName, listener);
177
+ this.signaler.offSignal(signalName, listener);
181
178
  return this;
182
179
  }
183
180
 
@@ -185,6 +182,6 @@ export class SignalManager extends DataObject<{ Events: IErrorEvent; }> implemen
185
182
  signalName: string,
186
183
  payload?: Jsonable,
187
184
  ) {
188
- this.manager.submitSignal(signalName, payload);
185
+ this.signaler.submitSignal(signalName, payload);
189
186
  }
190
187
  }
@@ -1,6 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- export * from "./signalManager";
6
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/signalManager/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,iBAAiB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/signalManager/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,iBAAiB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from \"./signalManager\";\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"signalManager.d.ts","sourceRoot":"","sources":["../../src/signalManager/signalManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AACjE,OAAO,EAAU,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAM5E,oBAAY,cAAc,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,KAAK,IAAI,CAAC;AAE3F;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;IACjE;;;;;;MAME;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;IACnE;;;;OAIG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,OAAE;CACxD;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,OAAE;IACxF,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI,CAAC;CAClD;AAED;;;;;;;;GAQG;AACH,qBAAa,QAAS,SAAQ,iBAAiB,CAAC,WAAW,CAAE,YAAW,SAAS;IAMzE;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAR7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAE9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;;IAG3C;;OAEG;IACc,QAAQ,EAAE,gBAAgB;IAC3C;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM;IAkBtB,OAAO,CAAC,oBAAoB;IAMrB,QAAQ,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,cAAc,GACzB,SAAS;IAML,SAAS,CACZ,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,cAAc,GACzB,SAAS;IAML,YAAY,CACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,QAAQ;CAOzB;AAED;;;;;;GAMG;AACH,qBAAa,aAAc,SAAQ,UAAU,CAAC;IAAE,MAAM,EAAE,WAAW,CAAC;CAAE,CAAE,YAAW,YAAY,EAAE,SAAS;IACtG,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,KAAK,OAAO,GAGlB;IAED,WAAkB,IAAI,WAA8C;IAEpE,gBAAuB,OAAO;gBATsB,WAAW;OAc7D;cAEc,cAAc;IASvB,QAAQ,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,cAAc,GACzB,SAAS;IAKL,SAAS,CACZ,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,cAAc,GACzB,SAAS;IAKL,YAAY,CACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,QAAQ;CAIzB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"signalManager.js","sourceRoot":"","sources":["../../src/signalManager/signalManager.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 { EventEmitter } from \"events\";\nimport { DataObject, DataObjectFactory } from \"@fluidframework/aqueduct\";\nimport { IErrorEvent } from \"@fluidframework/common-definitions\";\nimport { assert, TypedEventEmitter } from \"@fluidframework/common-utils\";\nimport { Jsonable } from \"@fluidframework/datastore-definitions\";\nimport { IInboundSignalMessage } from \"@fluidframework/runtime-definitions\";\n\n// TODO:\n// add way to mark with current sequence number for ordering signals relative to ops\n// throttling and batching\n\nexport type SignalListener = (clientId: string, local: boolean, payload: Jsonable) => void;\n\n/**\n * ISignaler defines an interface for working with signals that is similar to the more common\n * eventing patterns of EventEmitter. In addition to sending and responding to signals, it\n * provides explicit methods around signal requests to other connected clients.\n */\nexport interface ISignaler {\n /**\n * Adds a listener for the specified signal. It behaves in the same way as EventEmitter's `on`\n * method regarding multiple registrations, callback order, etc.\n * @param signalName - The name of the signal\n * @param listener - The callback signal handler to add\n * @returns This ISignaler\n */\n onSignal(signalName: string, listener: SignalListener): ISignaler;\n /**\n * Remove a listener for the specified signal. It behaves in the same way as EventEmitter's\n * `off` method regarding multiple registrations, removal order, etc.\n * @param signalName - The name of the signal\n * @param listener - The callback signal handler to remove\n * @returns This ISignaler\n */\n offSignal(signalName: string, listener: SignalListener): ISignaler;\n /**\n * Send a signal with payload to its connected listeners.\n * @param signalName - The name of the signal\n * @param payload - The data to send with the signal\n */\n submitSignal(signalName: string, payload?: Jsonable);\n}\n\n/**\n * Duck type of something that provides the expected signalling functionality:\n * A way to verify we can signal, a way to send a signal, and a way to listen for incoming signals\n */\nexport interface IRuntimeSignaler {\n connected: boolean;\n on(event: \"signal\", listener: (message: IInboundSignalMessage, local: boolean) => void);\n submitSignal(type: string, content: any): void;\n}\n\n/**\n * Note: currently experimental and under development\n *\n * Helper class to assist common scenarios around working with signals. Signaler wraps a runtime\n * object with signaling functionality (e.g. ContainerRuntime or FluidDataStoreRuntime) and can\n * then be used in place of the original signaler. It uses a separate internal EventEmitter to\n * manage callbacks, and thus will reflect that behavior with regards to callback registration and\n * deregistration.\n */\nexport class Signaler extends TypedEventEmitter<IErrorEvent> implements ISignaler {\n private readonly emitter = new EventEmitter();\n\n private readonly managerId: string | undefined;\n\n constructor(\n /**\n * Object to wrap that can submit and listen to signals\n */\n private readonly signaler: IRuntimeSignaler,\n /**\n * Optional id to assign to this manager that will be attached to\n * signal names. Useful to avoid collisions if there are multiple\n * signal users at the Container level\n */\n managerId?: string,\n ) {\n super();\n this.emitter.on(\"error\", (error) => {\n this.emit(\"error\", error);\n });\n this.managerId = managerId ? `#${managerId}` : undefined;\n this.signaler.on(\"signal\", (message: IInboundSignalMessage, local: boolean) => {\n const clientId = message.clientId;\n // Only call listeners when the runtime is connected and if the signal has an\n // identifiable sender clientId. The listener is responsible for deciding how\n // it wants to handle local/remote signals\n if (this.signaler.connected && clientId !== null) {\n this.emitter.emit(message.type, clientId, local, message.content);\n }\n });\n }\n\n private getManagerSignalName(signalName: string): string {\n return this.managerId ? `${signalName}${this.managerId}` : signalName;\n }\n\n // ISignaler methods\n\n public onSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n const managerSignalName = this.getManagerSignalName(signalName);\n this.emitter.on(managerSignalName, listener);\n return this;\n }\n\n public offSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n const managerSignalName = this.getManagerSignalName(signalName);\n this.emitter.off(managerSignalName, listener);\n return this;\n }\n\n public submitSignal(\n signalName: string,\n payload?: Jsonable,\n ) {\n const managerSignalName = this.getManagerSignalName(signalName);\n if (this.signaler.connected) {\n this.signaler.submitSignal(managerSignalName, payload);\n }\n }\n}\n\n/**\n * Note: currently experimental and under development\n *\n * DataObject implementation of ISignaler for fluid-static plug-and-play. Allows fluid-static\n * users to get an ISignaler without a custom DO. Where possible, consumers should instead\n * create a Signaler themselves instead of using the DO wrapper to avoid the DO overhead.\n */\nexport class SignalManager extends DataObject<{ Events: IErrorEvent; }> implements EventEmitter, ISignaler {\n private _manager: Signaler | undefined;\n private get manager(): Signaler {\n assert(this._manager !== undefined, 0x24b /* \"internal signaler should be defined\" */);\n return this._manager;\n }\n\n public static get Name() { return \"@fluid-example/signal-manager\"; }\n\n public static readonly factory = new DataObjectFactory(\n SignalManager.Name,\n SignalManager,\n [],\n {},\n );\n\n protected async hasInitialized() {\n this._manager = new Signaler(this.runtime);\n this.manager.on(\"error\", (error) => {\n this.emit(\"error\", error);\n });\n }\n\n // ISignaler methods Note these are all passthroughs\n\n public onSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n this.manager.onSignal(signalName, listener);\n return this;\n }\n\n public offSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n this.manager.offSignal(signalName, listener);\n return this;\n }\n\n public submitSignal(\n signalName: string,\n payload?: Jsonable,\n ) {\n this.manager.submitSignal(signalName, payload);\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/signalManager/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,iBAAiB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/signalManager/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,iBAAiB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from \"./signalManager\";\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"signalManager.d.ts","sourceRoot":"","sources":["../../src/signalManager/signalManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AACjE,OAAO,EAAU,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAM5E,oBAAY,cAAc,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,KAAK,IAAI,CAAC;AAE3F;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;IACjE;;;;;;MAME;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;IACnE;;;;OAIG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,OAAE;CACxD;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,OAAE;IACxF,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI,CAAC;CAClD;AAED;;;;;;;;GAQG;AACH,qBAAa,QAAS,SAAQ,iBAAiB,CAAC,WAAW,CAAE,YAAW,SAAS;IAMzE;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAR7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAE9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;;IAG3C;;OAEG;IACc,QAAQ,EAAE,gBAAgB;IAC3C;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM;IAkBtB,OAAO,CAAC,oBAAoB;IAMrB,QAAQ,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,cAAc,GACzB,SAAS;IAML,SAAS,CACZ,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,cAAc,GACzB,SAAS;IAML,YAAY,CACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,QAAQ;CAOzB;AAED;;;;;;GAMG;AACH,qBAAa,aAAc,SAAQ,UAAU,CAAC;IAAE,MAAM,EAAE,WAAW,CAAC;CAAE,CAAE,YAAW,YAAY,EAAE,SAAS;IACtG,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,KAAK,OAAO,GAGlB;IAED,WAAkB,IAAI,WAA8C;IAEpE,gBAAuB,OAAO;gBATsB,WAAW;OAc7D;cAEc,cAAc;IASvB,QAAQ,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,cAAc,GACzB,SAAS;IAKL,SAAS,CACZ,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,cAAc,GACzB,SAAS;IAKL,YAAY,CACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,QAAQ;CAIzB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"signalManager.js","sourceRoot":"","sources":["../../src/signalManager/signalManager.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 { EventEmitter } from \"events\";\nimport { DataObject, DataObjectFactory } from \"@fluidframework/aqueduct\";\nimport { IErrorEvent } from \"@fluidframework/common-definitions\";\nimport { assert, TypedEventEmitter } from \"@fluidframework/common-utils\";\nimport { Jsonable } from \"@fluidframework/datastore-definitions\";\nimport { IInboundSignalMessage } from \"@fluidframework/runtime-definitions\";\n\n// TODO:\n// add way to mark with current sequence number for ordering signals relative to ops\n// throttling and batching\n\nexport type SignalListener = (clientId: string, local: boolean, payload: Jsonable) => void;\n\n/**\n * ISignaler defines an interface for working with signals that is similar to the more common\n * eventing patterns of EventEmitter. In addition to sending and responding to signals, it\n * provides explicit methods around signal requests to other connected clients.\n */\nexport interface ISignaler {\n /**\n * Adds a listener for the specified signal. It behaves in the same way as EventEmitter's `on`\n * method regarding multiple registrations, callback order, etc.\n * @param signalName - The name of the signal\n * @param listener - The callback signal handler to add\n * @returns This ISignaler\n */\n onSignal(signalName: string, listener: SignalListener): ISignaler;\n /**\n * Remove a listener for the specified signal. It behaves in the same way as EventEmitter's\n * `off` method regarding multiple registrations, removal order, etc.\n * @param signalName - The name of the signal\n * @param listener - The callback signal handler to remove\n * @returns This ISignaler\n */\n offSignal(signalName: string, listener: SignalListener): ISignaler;\n /**\n * Send a signal with payload to its connected listeners.\n * @param signalName - The name of the signal\n * @param payload - The data to send with the signal\n */\n submitSignal(signalName: string, payload?: Jsonable);\n}\n\n/**\n * Duck type of something that provides the expected signalling functionality:\n * A way to verify we can signal, a way to send a signal, and a way to listen for incoming signals\n */\nexport interface IRuntimeSignaler {\n connected: boolean;\n on(event: \"signal\", listener: (message: IInboundSignalMessage, local: boolean) => void);\n submitSignal(type: string, content: any): void;\n}\n\n/**\n * Note: currently experimental and under development\n *\n * Helper class to assist common scenarios around working with signals. Signaler wraps a runtime\n * object with signaling functionality (e.g. ContainerRuntime or FluidDataStoreRuntime) and can\n * then be used in place of the original signaler. It uses a separate internal EventEmitter to\n * manage callbacks, and thus will reflect that behavior with regards to callback registration and\n * deregistration.\n */\nexport class Signaler extends TypedEventEmitter<IErrorEvent> implements ISignaler {\n private readonly emitter = new EventEmitter();\n\n private readonly managerId: string | undefined;\n\n constructor(\n /**\n * Object to wrap that can submit and listen to signals\n */\n private readonly signaler: IRuntimeSignaler,\n /**\n * Optional id to assign to this manager that will be attached to\n * signal names. Useful to avoid collisions if there are multiple\n * signal users at the Container level\n */\n managerId?: string,\n ) {\n super();\n this.emitter.on(\"error\", (error) => {\n this.emit(\"error\", error);\n });\n this.managerId = managerId ? `#${managerId}` : undefined;\n this.signaler.on(\"signal\", (message: IInboundSignalMessage, local: boolean) => {\n const clientId = message.clientId;\n // Only call listeners when the runtime is connected and if the signal has an\n // identifiable sender clientId. The listener is responsible for deciding how\n // it wants to handle local/remote signals\n if (this.signaler.connected && clientId !== null) {\n this.emitter.emit(message.type, clientId, local, message.content);\n }\n });\n }\n\n private getManagerSignalName(signalName: string): string {\n return this.managerId ? `${signalName}${this.managerId}` : signalName;\n }\n\n // ISignaler methods\n\n public onSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n const managerSignalName = this.getManagerSignalName(signalName);\n this.emitter.on(managerSignalName, listener);\n return this;\n }\n\n public offSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n const managerSignalName = this.getManagerSignalName(signalName);\n this.emitter.off(managerSignalName, listener);\n return this;\n }\n\n public submitSignal(\n signalName: string,\n payload?: Jsonable,\n ) {\n const managerSignalName = this.getManagerSignalName(signalName);\n if (this.signaler.connected) {\n this.signaler.submitSignal(managerSignalName, payload);\n }\n }\n}\n\n/**\n * Note: currently experimental and under development\n *\n * DataObject implementation of ISignaler for fluid-static plug-and-play. Allows fluid-static\n * users to get an ISignaler without a custom DO. Where possible, consumers should instead\n * create a Signaler themselves instead of using the DO wrapper to avoid the DO overhead.\n */\nexport class SignalManager extends DataObject<{ Events: IErrorEvent; }> implements EventEmitter, ISignaler {\n private _manager: Signaler | undefined;\n private get manager(): Signaler {\n assert(this._manager !== undefined, 0x24b /* \"internal signaler should be defined\" */);\n return this._manager;\n }\n\n public static get Name() { return \"@fluid-example/signal-manager\"; }\n\n public static readonly factory = new DataObjectFactory(\n SignalManager.Name,\n SignalManager,\n [],\n {},\n );\n\n protected async hasInitialized() {\n this._manager = new Signaler(this.runtime);\n this.manager.on(\"error\", (error) => {\n this.emit(\"error\", error);\n });\n }\n\n // ISignaler methods Note these are all passthroughs\n\n public onSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n this.manager.onSignal(signalName, listener);\n return this;\n }\n\n public offSignal(\n signalName: string,\n listener: SignalListener,\n ): ISignaler {\n this.manager.offSignal(signalName, listener);\n return this;\n }\n\n public submitSignal(\n signalName: string,\n payload?: Jsonable,\n ) {\n this.manager.submitSignal(signalName, payload);\n }\n}\n"]}
@@ -1,55 +0,0 @@
1
- # SignalManager
2
- The `SignalManager` is a DataObject that can be used to communicate transient data via signals. Transient data refers to impermanent information that is not persisted with the container.
3
-
4
- ## Usage
5
- User presence scenarios are well-suited for `SignalManager`, as users are required to tell other users their own information and their past data is mostly irrelavant. Using `SignalManager` over other distributed data structures in these scenarios is beneficial, as its usage does not result in the storage of data that is not useful in the long-term.
6
-
7
- ### Creation
8
- Just like with DDSes, you can include `SignalManager` as a shared object you would like to load in your `FluidContainer` schema.
9
-
10
- Here is a look at how you would go about loading `SignalManager` as part of the initial objects of the container:
11
-
12
- ```typescript
13
- const containerSchema: ContainerSchema = {
14
- initialObjects: {
15
- signalManager: SignalManager,
16
- },
17
- };
18
-
19
- const { container, services } = await client.createContainer(containerSchema);
20
-
21
- const signalManager = container.initialObjects.signalManager as SignalManager;
22
- ```
23
-
24
- `signalManager` can then be directly used in your Fluid application!
25
-
26
- For more information on using `ContainerSchema` to create objects please see [Data modeling](https://fluidframework.com/docs/build/data-modeling/).
27
-
28
- ## API
29
- `SignalManager` provides a few simple methods to send signals and add/remove listeners to specific signals as well:
30
- - `submitSignal(signalName: string, payload?: Jsonable)` - Sends a signal with a payload to its connected listeners
31
- - `onSignal(signalName: string, listener: SignalListener)` - Adds a listener for the specified signal. Same behavior as EventEmitter's `on` method.
32
- - `offSignal(signalName: string, listener: SignalListener)` - Removes a listener for the specified signal. Same behavior as EventEmitter's `off` method.
33
-
34
- ## Common Patterns
35
- ### Signal Request
36
- When a client joins a collaboration session, they may need to receive pertinent information immediately after connecting the container. To support this, they can request a specific signal be sent to them from other connected clients within the application. For example, in the [FocusTracker](https://github.com/microsoft/FluidFramework/tree/main/examples/data-objects/focus-tracker) we define a "focusRequest" signal type that a newly joining client uses to request the focus-state of each currently connected client:
37
-
38
- ```typescript
39
- private static readonly focusRequestType = "focusRequest";
40
- ```
41
-
42
- ```typescript
43
- container.on("connected", () => {
44
- this.signalManager.submitSignal(FocusTracker.focusRequestType);
45
- });
46
- ```
47
-
48
- The connected clients are listening to this focus request signal, and they respond with their current focus state:
49
-
50
- ```typescript
51
- this.signalManager.onSignal(FocusTracker.focusRequestType, () => {
52
- this.sendFocusSignal(document.hasFocus());
53
- });
54
- ```
55
- When there are a lot of connected clients, usage of this request pattern can lead to high signal costs incurred from large amounts of signals being submitted all at the same time. While this pattern is helpful when a client is in need of relevant information, to limit signal costs it would be beneficial to examine whether or not the requested data will be quickly avaiable from other events being listened to within the application. Take [MouseTracker]() as an example, a newly connecting client is not required to request a signal to receive every current mouse position on the document. Since mouse movements are frequent, the newly connecting client can simply wait to recieve other users mouse positions on their mousemove events.