@fluidframework/container-loader 0.54.2 → 0.56.0-49831

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 (77) hide show
  1. package/.eslintrc.js +1 -1
  2. package/dist/connectionStateHandler.d.ts +1 -0
  3. package/dist/connectionStateHandler.d.ts.map +1 -1
  4. package/dist/connectionStateHandler.js +11 -2
  5. package/dist/connectionStateHandler.js.map +1 -1
  6. package/dist/container.d.ts +6 -12
  7. package/dist/container.d.ts.map +1 -1
  8. package/dist/container.js +50 -58
  9. package/dist/container.js.map +1 -1
  10. package/dist/containerContext.d.ts +11 -3
  11. package/dist/containerContext.d.ts.map +1 -1
  12. package/dist/containerContext.js +12 -6
  13. package/dist/containerContext.js.map +1 -1
  14. package/dist/containerStorageAdapter.d.ts +1 -1
  15. package/dist/containerStorageAdapter.d.ts.map +1 -1
  16. package/dist/containerStorageAdapter.js.map +1 -1
  17. package/dist/deltaManager.d.ts +0 -11
  18. package/dist/deltaManager.d.ts.map +1 -1
  19. package/dist/deltaManager.js +0 -13
  20. package/dist/deltaManager.js.map +1 -1
  21. package/dist/deltaManagerProxy.d.ts +0 -1
  22. package/dist/deltaManagerProxy.d.ts.map +1 -1
  23. package/dist/deltaManagerProxy.js +0 -3
  24. package/dist/deltaManagerProxy.js.map +1 -1
  25. package/dist/loader.d.ts +3 -3
  26. package/dist/loader.d.ts.map +1 -1
  27. package/dist/loader.js.map +1 -1
  28. package/dist/packageVersion.d.ts +1 -1
  29. package/dist/packageVersion.d.ts.map +1 -1
  30. package/dist/packageVersion.js +1 -1
  31. package/dist/packageVersion.js.map +1 -1
  32. package/dist/retriableDocumentStorageService.d.ts +1 -1
  33. package/dist/retriableDocumentStorageService.d.ts.map +1 -1
  34. package/dist/retriableDocumentStorageService.js.map +1 -1
  35. package/lib/connectionStateHandler.d.ts +1 -0
  36. package/lib/connectionStateHandler.d.ts.map +1 -1
  37. package/lib/connectionStateHandler.js +11 -2
  38. package/lib/connectionStateHandler.js.map +1 -1
  39. package/lib/container.d.ts +6 -12
  40. package/lib/container.d.ts.map +1 -1
  41. package/lib/container.js +52 -60
  42. package/lib/container.js.map +1 -1
  43. package/lib/containerContext.d.ts +11 -3
  44. package/lib/containerContext.d.ts.map +1 -1
  45. package/lib/containerContext.js +12 -6
  46. package/lib/containerContext.js.map +1 -1
  47. package/lib/containerStorageAdapter.d.ts +1 -1
  48. package/lib/containerStorageAdapter.d.ts.map +1 -1
  49. package/lib/containerStorageAdapter.js.map +1 -1
  50. package/lib/deltaManager.d.ts +0 -11
  51. package/lib/deltaManager.d.ts.map +1 -1
  52. package/lib/deltaManager.js +0 -13
  53. package/lib/deltaManager.js.map +1 -1
  54. package/lib/deltaManagerProxy.d.ts +0 -1
  55. package/lib/deltaManagerProxy.d.ts.map +1 -1
  56. package/lib/deltaManagerProxy.js +0 -3
  57. package/lib/deltaManagerProxy.js.map +1 -1
  58. package/lib/loader.d.ts +3 -3
  59. package/lib/loader.d.ts.map +1 -1
  60. package/lib/loader.js.map +1 -1
  61. package/lib/packageVersion.d.ts +1 -1
  62. package/lib/packageVersion.d.ts.map +1 -1
  63. package/lib/packageVersion.js +1 -1
  64. package/lib/packageVersion.js.map +1 -1
  65. package/lib/retriableDocumentStorageService.d.ts +1 -1
  66. package/lib/retriableDocumentStorageService.d.ts.map +1 -1
  67. package/lib/retriableDocumentStorageService.js.map +1 -1
  68. package/package.json +19 -18
  69. package/src/connectionStateHandler.ts +13 -3
  70. package/src/container.ts +71 -69
  71. package/src/containerContext.ts +18 -9
  72. package/src/containerStorageAdapter.ts +1 -1
  73. package/src/deltaManager.ts +0 -14
  74. package/src/deltaManagerProxy.ts +0 -4
  75. package/src/loader.ts +3 -3
  76. package/src/packageVersion.ts +1 -1
  77. package/src/retriableDocumentStorageService.ts +1 -1
package/.eslintrc.js CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  module.exports = {
7
7
  "extends": [
8
- "@fluidframework/eslint-config-fluid/eslint7"
8
+ "@fluidframework/eslint-config-fluid"
9
9
  ],
10
10
  "parserOptions": {
11
11
  "project": ["./tsconfig.json", "./src/test/tsconfig.json"]
@@ -35,6 +35,7 @@ export declare class ConnectionStateHandler {
35
35
  private startJoinOpTimer;
36
36
  private stopJoinOpTimer;
37
37
  dispose(): void;
38
+ containerSaved(): void;
38
39
  receivedAddMemberEvent(clientId: string): void;
39
40
  private applyForConnectedState;
40
41
  receivedRemoveMemberEvent(clientId: string): void;
@@ -1 +1 @@
1
- {"version":3,"file":"connectionStateHandler.d.ts","sourceRoot":"","sources":["../src/connectionStateHandler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAGxF,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,uBAAuB;IACpC,eAAe,EAAE,MAAM,iBAAiB,GAAG,SAAS,CAAC;IACrD,iCAAiC,EAC7B,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC7F,qBAAqB,EAAE,MAAM,OAAO,CAAC;IACrC,sBAAsB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,sBAAsB,EAAE,MAAM,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC3D,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B;AAID,qBAAa,sBAAsB;IA0B3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IA1B3B,OAAO,CAAC,gBAAgB,CAAgC;IACxD,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAQ;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IAEpC,OAAO,CAAC,SAAS,CAA+B;IAEhD,IAAW,eAAe,IAAI,eAAe,CAE5C;IAED,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED,IAAW,QAAQ,IAAI,MAAM,GAAG,SAAS,CAExC;IAED,IAAW,eAAe,IAAI,MAAM,GAAG,SAAS,CAE/C;gBAGoB,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,gBAAgB;IA2B7C,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,eAAe;IAKhB,OAAO;IAKP,sBAAsB,CAAC,QAAQ,EAAE,MAAM;IAsB9C,OAAO,CAAC,sBAAsB;IA4BvB,yBAAyB,CAAC,QAAQ,EAAE,MAAM;IAQ1C,uBAAuB,CAAC,MAAM,EAAE,MAAM;IAOtC,oBAAoB,CACvB,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,kBAAkB;IAgC/B,OAAO,CAAC,kBAAkB;CAuD7B"}
1
+ {"version":3,"file":"connectionStateHandler.d.ts","sourceRoot":"","sources":["../src/connectionStateHandler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAGxF,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,uBAAuB;IACpC,eAAe,EAAE,MAAM,iBAAiB,GAAG,SAAS,CAAC;IACrD,iCAAiC,EAC7B,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC7F,qBAAqB,EAAE,MAAM,OAAO,CAAC;IACrC,sBAAsB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,sBAAsB,EAAE,MAAM,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC3D,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B;AAID,qBAAa,sBAAsB;IA0B3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IA1B3B,OAAO,CAAC,gBAAgB,CAAgC;IACxD,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAQ;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IAEpC,OAAO,CAAC,SAAS,CAA+B;IAEhD,IAAW,eAAe,IAAI,eAAe,CAE5C;IAED,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED,IAAW,QAAQ,IAAI,MAAM,GAAG,SAAS,CAExC;IAED,IAAW,eAAe,IAAI,MAAM,GAAG,SAAS,CAE/C;gBAGoB,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,gBAAgB;IA4B7C,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,eAAe;IAKhB,OAAO;IAKP,cAAc;IASd,sBAAsB,CAAC,QAAQ,EAAE,MAAM;IAsB9C,OAAO,CAAC,sBAAsB;IA4BvB,yBAAyB,CAAC,QAAQ,EAAE,MAAM;IAQ1C,uBAAuB,CAAC,MAAM,EAAE,MAAM;IAOtC,oBAAoB,CACvB,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,kBAAkB;IAgC/B,OAAO,CAAC,kBAAkB;CAuD7B"}
@@ -16,8 +16,9 @@ class ConnectionStateHandler {
16
16
  this.logger = logger;
17
17
  this._connectionState = container_1.ConnectionState.Disconnected;
18
18
  this.prevClientLeftTimer = new common_utils_1.Timer((_a =
19
- // Default is 90 sec for which we are going to wait for its own "leave" message.
20
- this.handler.maxClientLeaveWaitTime) !== null && _a !== void 0 ? _a : 90000, () => {
19
+ // Default is 5 min for which we are going to wait for its own "leave" message. This is same as
20
+ // the max time on server after which leave op is sent.
21
+ this.handler.maxClientLeaveWaitTime) !== null && _a !== void 0 ? _a : 300000, () => {
21
22
  common_utils_1.assert(!this.connected, 0x2ac /* "Connected when timeout waiting for leave from previous session fired!" */);
22
23
  this.applyForConnectedState("timeout");
23
24
  });
@@ -56,6 +57,14 @@ class ConnectionStateHandler {
56
57
  common_utils_1.assert(!this.joinOpTimer.hasTimer, 0x2a5 /* "join timer" */);
57
58
  this.prevClientLeftTimer.clear();
58
59
  }
60
+ containerSaved() {
61
+ // If we were waiting for moving to Connected state, then only apply for state change. Since the container
62
+ // is now saved and we don't have any ops to roundtrip, we can clear the timer and apply for connected state.
63
+ if (this.prevClientLeftTimer.hasTimer) {
64
+ this.prevClientLeftTimer.clear();
65
+ this.applyForConnectedState("containerSaved");
66
+ }
67
+ }
59
68
  receivedAddMemberEvent(clientId) {
60
69
  // This is the only one that requires the pending client ID
61
70
  if (clientId === this.pendingClientId) {
@@ -1 +1 @@
1
- {"version":3,"file":"connectionStateHandler.js","sourceRoot":"","sources":["../src/connectionStateHandler.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAMH,qEAAmE;AACnE,+DAA6D;AAC7D,2CAA8C;AAgB9C,MAAM,WAAW,GAAG,KAAK,CAAC;AAE1B,MAAa,sBAAsB;IAyB/B,YACqB,OAAgC,EAChC,MAAwB;;QADxB,YAAO,GAAP,OAAO,CAAyB;QAChC,WAAM,GAAN,MAAM,CAAkB;QA1BrC,qBAAgB,GAAG,2BAAe,CAAC,YAAY,CAAC;QA4BpD,IAAI,CAAC,mBAAmB,GAAG,IAAI,oBAAK;QAChC,gFAAgF;QAChF,IAAI,CAAC,OAAO,CAAC,sBAAsB,mCAAI,KAAK,EAC5C,GAAG,EAAE;YACD,qBAAM,CAAC,CAAC,IAAI,CAAC,SAAS,EAClB,KAAK,CAAC,6EAA6E,CAAC,CAAC;YACzF,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;QAC3C,CAAC,CACJ,CAAC;QAEF,qGAAqG;QACrG,kGAAkG;QAClG,iEAAiE;QACjE,IAAI,CAAC,WAAW,GAAG,IAAI,oBAAK,CACxB,WAAW,EACX,GAAG,EAAE;YACD,gFAAgF;YAChF,iGAAiG;YACjG,IAAI,IAAI,CAAC,eAAe,KAAK,2BAAe,CAAC,UAAU,EAAE;gBACrD,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC;aAC/C;QACL,CAAC,CACJ,CAAC;IACN,CAAC;IA3CD,IAAW,eAAe;QACtB,OAAO,IAAI,CAAC,gBAAgB,CAAC;IACjC,CAAC;IAED,IAAW,SAAS;QAChB,OAAO,IAAI,CAAC,eAAe,KAAK,2BAAe,CAAC,SAAS,CAAC;IAC9D,CAAC;IAED,IAAW,QAAQ;QACf,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED,IAAW,eAAe;QACtB,OAAO,IAAI,CAAC,gBAAgB,CAAC;IACjC,CAAC;IA+BO,gBAAgB;QACpB,qBAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAClE,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IAEO,eAAe;QACnB,qBAAM,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAChE,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IAEM,OAAO;QACV,qBAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAC7D,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC;IACrC,CAAC;IAEM,sBAAsB,CAAC,QAAgB;QAC1C,2DAA2D;QAC3D,IAAI,QAAQ,KAAK,IAAI,CAAC,eAAe,EAAE;YACnC,IAAI,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE;gBAC3B,IAAI,CAAC,eAAe,EAAE,CAAC;aAC1B;iBAAM;gBACH,oEAAoE;gBACpE,+CAA+C;gBAC/C,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;aACrD;YACD,+DAA+D;YAC/D,IAAI,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE;gBACnC,IAAI,CAAC,SAAS,GAAG,kCAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE;oBACjD,SAAS,EAAE,uBAAuB;oBAClC,cAAc,EAAE,IAAI,CAAC,SAAS;oBAC9B,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE;iBAC1D,CAAC,CAAC;aACN;YACD,IAAI,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;SACjD;IACL,CAAC;IAEO,sBAAsB,CAAC,MAA0D;;QACrF,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;QACvD,qBAAM,CAAC,eAAe,KAAK,SAAS,EAAE,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACjG,uFAAuF;QACvF,4FAA4F;QAC5F,yCAAyC;QACzC,IAAI,IAAI,CAAC,eAAe,KAAK,IAAI,CAAC,QAAQ;eACnC,IAAI,CAAC,eAAe,KAAK,SAAS;eAClC,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,SAAS;eACpE,CAAC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EACvC;YACE,MAAA,IAAI,CAAC,SAAS,0CAAE,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE;YAChC,IAAI,CAAC,kBAAkB,CAAC,2BAAe,CAAC,SAAS,CAAC,CAAC;SACtD;aAAM;YACH,2FAA2F;YAC3F,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC;gBAC3B,SAAS,EAAE,wBAAwB;gBACnC,QAAQ,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;gBACpD,MAAM;gBACN,eAAe,EAAE,IAAI,CAAC,eAAe;gBACrC,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,QAAQ,EAAE,IAAI,CAAC,mBAAmB,CAAC,QAAQ;gBAC3C,QAAQ,EAAE,eAAe,KAAK,SAAS,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS;uBACtE,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,SAAS;aAC9E,CAAC,CAAC;SACN;IACL,CAAC;IAEM,yBAAyB,CAAC,QAAgB;QAC7C,8DAA8D;QAC9D,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE;YAC5B,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC;YACjC,IAAI,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,CAAC;SACpD;IACL,CAAC;IAEM,uBAAuB,CAAC,MAAc;QACzC,IAAI,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE;YAC3B,IAAI,CAAC,eAAe,EAAE,CAAC;SAC1B;QACD,IAAI,CAAC,kBAAkB,CAAC,2BAAe,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAClE,CAAC;IAEM,oBAAoB,CACvB,cAA8B,EAC9B,OAA2B;QAE3B,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACvC,IAAI,CAAC,gBAAgB,GAAG,2BAAe,CAAC,UAAU,CAAC;QAEnD,wGAAwG;QACxG,qDAAqD;QACrD,+FAA+F;QAC/F,6FAA6F;QAC7F,6FAA6F;QAC7F,2FAA2F;QAC3F,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;QAEzC,8FAA8F;QAC9F,IAAI,CAAC,OAAO,CAAC,iCAAiC,CAAC,2BAAe,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAErF,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;QACvD,uEAAuE;QACvE,iFAAiF;QACjF,kGAAkG;QAClG,oCAAoC;QACpC,mGAAmG;QACnG,IAAI,CAAC,eAAe,KAAK,SAAS,IAAI,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,SAAS,CAAC;eAChG,cAAc,KAAK,MAAM,EAC9B;YACE,qBAAM,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC,uDAAuD,CAAC,CAAC;YAC1G,IAAI,CAAC,kBAAkB,CAAC,2BAAe,CAAC,SAAS,CAAC,CAAC;SACtD;aAAM,IAAI,cAAc,KAAK,OAAO,EAAE;YACnC,IAAI,CAAC,gBAAgB,EAAE,CAAC;SAC3B;IACL,CAAC;IAIO,kBAAkB,CAAC,KAAsB,EAAE,MAAe;;QAC9D,IAAI,IAAI,CAAC,eAAe,KAAK,KAAK,EAAE;YAChC,4CAA4C;YAC5C,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,wBAAwB,EAAE,KAAK,EAAE,CAAC,CAAC;YAC3E,OAAO;SACV;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACvC,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;QAC9B,MAAM,MAAM,SAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,0CAAE,MAAM,CAAC;QACtD,IAAI,MAAyC,CAAC;QAC9C,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE;YAC9B,MAAM,GAAG,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;SAC9C;QACD,IAAI,KAAK,KAAK,2BAAe,CAAC,SAAS,EAAE;YACrC,qBAAM,CAAC,QAAQ,KAAK,2BAAe,CAAC,UAAU,EAC1C,KAAK,CAAC,oDAAoD,CAAC,CAAC;YAChE,yEAAyE;YACzE,IAAI,MAAM,KAAK,SAAS,EAAE;gBACtB,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC;aAChC;YACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC;SACzC;aAAM,IAAI,KAAK,KAAK,2BAAe,CAAC,YAAY,EAAE;YAC/C,4EAA4E;YAC5E,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;YAClC,oGAAoG;YACpG,sGAAsG;YACtG,mCAAmC;YACnC,uGAAuG;YACvG,qGAAqG;YACrG,sGAAsG;YACtG,IAAI,MAAM,KAAK,SAAS;mBACjB,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE;mBACpC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,KAAK,KAAK,EAChD;gBACE,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,CAAC;aACtC;iBAAM;gBACH,2FAA2F;gBAC3F,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC;oBAC3B,SAAS,EAAE,sBAAsB;oBACjC,QAAQ,EAAE,MAAM,KAAK,SAAS;oBAC9B,QAAQ,EAAE,IAAI,CAAC,mBAAmB,CAAC,QAAQ;oBAC3C,qBAAqB,EAAE,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE;iBAC9D,CAAC,CAAC;aACN;SACJ;QAED,4DAA4D;QAC5D,IAAI,CAAC,OAAO,CAAC,iCAAiC,CAAC,IAAI,CAAC,gBAAgB,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QAExF,gCAAgC;QAChC,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE,CAAC;IAC1C,CAAC;CACJ;AA/ND,wDA+NC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { IConnectionDetails } from \"@fluidframework/container-definitions\";\nimport { ProtocolOpHandler } from \"@fluidframework/protocol-base\";\nimport { ConnectionMode, ISequencedClient } from \"@fluidframework/protocol-definitions\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { assert, Timer } from \"@fluidframework/common-utils\";\nimport { ConnectionState } from \"./container\";\n\nexport interface IConnectionStateHandler {\n protocolHandler: () => ProtocolOpHandler | undefined,\n logConnectionStateChangeTelemetry:\n (value: ConnectionState, oldState: ConnectionState, reason?: string | undefined) => void,\n shouldClientJoinWrite: () => boolean,\n maxClientLeaveWaitTime: number | undefined,\n logConnectionIssue: (eventName: string) => void,\n connectionStateChanged: () => void,\n}\n\nexport interface ILocalSequencedClient extends ISequencedClient {\n shouldHaveLeft?: boolean;\n}\n\nconst JoinOpTimer = 45000;\n\nexport class ConnectionStateHandler {\n private _connectionState = ConnectionState.Disconnected;\n private _pendingClientId: string | undefined;\n private _clientId: string | undefined;\n private readonly prevClientLeftTimer: Timer;\n private readonly joinOpTimer: Timer;\n\n private waitEvent: PerformanceEvent | undefined;\n\n public get connectionState(): ConnectionState {\n return this._connectionState;\n }\n\n public get connected(): boolean {\n return this.connectionState === ConnectionState.Connected;\n }\n\n public get clientId(): string | undefined {\n return this._clientId;\n }\n\n public get pendingClientId(): string | undefined {\n return this._pendingClientId;\n }\n\n constructor(\n private readonly handler: IConnectionStateHandler,\n private readonly logger: ITelemetryLogger,\n ) {\n this.prevClientLeftTimer = new Timer(\n // Default is 90 sec for which we are going to wait for its own \"leave\" message.\n this.handler.maxClientLeaveWaitTime ?? 90000,\n () => {\n assert(!this.connected,\n 0x2ac /* \"Connected when timeout waiting for leave from previous session fired!\" */);\n this.applyForConnectedState(\"timeout\");\n },\n );\n\n // Based on recent data, it looks like majority of cases where we get stuck are due to really slow or\n // timing out ops fetches. So attempt recovery infrequently. Also fetch uses 30 second timeout, so\n // if retrying fixes the problem, we should not see these events.\n this.joinOpTimer = new Timer(\n JoinOpTimer,\n () => {\n // I've observed timer firing within couple ms from disconnect event, looks like\n // queued timer callback is not cancelled if timer is cancelled while callback sits in the queue.\n if (this.connectionState === ConnectionState.Connecting) {\n this.handler.logConnectionIssue(\"NoJoinOp\");\n }\n },\n );\n }\n\n private startJoinOpTimer() {\n assert(!this.joinOpTimer.hasTimer, 0x234 /* \"has joinOpTimer\" */);\n this.joinOpTimer.start();\n }\n\n private stopJoinOpTimer() {\n assert(this.joinOpTimer.hasTimer, 0x235 /* \"no joinOpTimer\" */);\n this.joinOpTimer.clear();\n }\n\n public dispose() {\n assert(!this.joinOpTimer.hasTimer, 0x2a5 /* \"join timer\" */);\n this.prevClientLeftTimer.clear();\n }\n\n public receivedAddMemberEvent(clientId: string) {\n // This is the only one that requires the pending client ID\n if (clientId === this.pendingClientId) {\n if (this.joinOpTimer.hasTimer) {\n this.stopJoinOpTimer();\n } else {\n // timer has already fired, meaning it took too long to get join on.\n // Record how long it actually took to recover.\n this.handler.logConnectionIssue(\"ReceivedJoinOp\");\n }\n // Start the event in case we are waiting for leave or timeout.\n if (this.prevClientLeftTimer.hasTimer) {\n this.waitEvent = PerformanceEvent.start(this.logger, {\n eventName: \"WaitBeforeClientLeave\",\n waitOnClientId: this._clientId,\n hadOutstandingOps: this.handler.shouldClientJoinWrite(),\n });\n }\n this.applyForConnectedState(\"addMemberEvent\");\n }\n }\n\n private applyForConnectedState(source: \"removeMemberEvent\" | \"addMemberEvent\" | \"timeout\") {\n const protocolHandler = this.handler.protocolHandler();\n assert(protocolHandler !== undefined, 0x236 /* \"In all cases it should be already installed\" */);\n // Move to connected state only if we are in Connecting state, we have seen our join op\n // and there is no timer running which means we are not waiting for previous client to leave\n // or timeout has occured while doing so.\n if (this.pendingClientId !== this.clientId\n && this.pendingClientId !== undefined\n && protocolHandler.quorum.getMember(this.pendingClientId) !== undefined\n && !this.prevClientLeftTimer.hasTimer\n ) {\n this.waitEvent?.end({ source });\n this.setConnectionState(ConnectionState.Connected);\n } else {\n // Adding this event temporarily so that we can get help debugging if something goes wrong.\n this.logger.sendTelemetryEvent({\n eventName: \"connectedStateRejected\",\n category: source === \"timeout\" ? \"error\" : \"generic\",\n source,\n pendingClientId: this.pendingClientId,\n clientId: this.clientId,\n hasTimer: this.prevClientLeftTimer.hasTimer,\n inQuorum: protocolHandler !== undefined && this.pendingClientId !== undefined\n && protocolHandler.quorum.getMember(this.pendingClientId) !== undefined,\n });\n }\n }\n\n public receivedRemoveMemberEvent(clientId: string) {\n // If the client which has left was us, then finish the timer.\n if (this.clientId === clientId) {\n this.prevClientLeftTimer.clear();\n this.applyForConnectedState(\"removeMemberEvent\");\n }\n }\n\n public receivedDisconnectEvent(reason: string) {\n if (this.joinOpTimer.hasTimer) {\n this.stopJoinOpTimer();\n }\n this.setConnectionState(ConnectionState.Disconnected, reason);\n }\n\n public receivedConnectEvent(\n connectionMode: ConnectionMode,\n details: IConnectionDetails,\n ) {\n const oldState = this._connectionState;\n this._connectionState = ConnectionState.Connecting;\n\n // Stash the clientID to detect when transitioning from connecting (socket.io channel open) to connected\n // (have received the join message for the client ID)\n // This is especially important in the reconnect case. It's possible there could be outstanding\n // ops sent by this client, so we should keep the old client id until we see our own client's\n // join message. after we see the join message for out new connection with our new client id,\n // we know there can no longer be outstanding ops that we sent with the previous client id.\n this._pendingClientId = details.clientId;\n\n // Report telemetry after we set client id, but before transitioning to Connected state below!\n this.handler.logConnectionStateChangeTelemetry(ConnectionState.Connecting, oldState);\n\n const protocolHandler = this.handler.protocolHandler();\n // Check if we already processed our own join op through delta storage!\n // we are fetching ops from storage in parallel to connecting to ordering service\n // Given async processes, it's possible that we have already processed our own join message before\n // connection was fully established.\n // Note that we might be still initializing quorum - connection is established proactively on load!\n if ((protocolHandler !== undefined && protocolHandler.quorum.getMember(details.clientId) !== undefined)\n || connectionMode === \"read\"\n ) {\n assert(!this.prevClientLeftTimer.hasTimer, 0x2a6 /* \"there should be no timer for 'read' connections\" */);\n this.setConnectionState(ConnectionState.Connected);\n } else if (connectionMode === \"write\") {\n this.startJoinOpTimer();\n }\n }\n\n private setConnectionState(value: ConnectionState.Disconnected, reason: string);\n private setConnectionState(value: ConnectionState.Connected);\n private setConnectionState(value: ConnectionState, reason?: string) {\n if (this.connectionState === value) {\n // Already in the desired state - exit early\n this.logger.sendErrorEvent({ eventName: \"setConnectionStateSame\", value });\n return;\n }\n\n const oldState = this._connectionState;\n this._connectionState = value;\n const quorum = this.handler.protocolHandler()?.quorum;\n let client: ILocalSequencedClient | undefined;\n if (this._clientId !== undefined) {\n client = quorum?.getMember(this._clientId);\n }\n if (value === ConnectionState.Connected) {\n assert(oldState === ConnectionState.Connecting,\n 0x1d8 /* \"Should only transition from Connecting state\" */);\n // Mark our old client should have left in the quorum if it's still there\n if (client !== undefined) {\n client.shouldHaveLeft = true;\n }\n this._clientId = this.pendingClientId;\n } else if (value === ConnectionState.Disconnected) {\n // Important as we process our own joinSession message through delta request\n this._pendingClientId = undefined;\n // Only wait for \"leave\" message if the connected client exists in the quorum because only the write\n // client will exist in the quorum and only for those clients we will receive \"removeMember\" event and\n // the client has some unacked ops.\n // Also server would not accept ops from read client. Also check if the timer is not already running as\n // we could receive \"Disconnected\" event multiple times without getting connected and in that case we\n // don't want to reset the timer as we still want to wait on original client which started this timer.\n if (client !== undefined\n && this.handler.shouldClientJoinWrite()\n && this.prevClientLeftTimer.hasTimer === false\n ) {\n this.prevClientLeftTimer.restart();\n } else {\n // Adding this event temporarily so that we can get help debugging if something goes wrong.\n this.logger.sendTelemetryEvent({\n eventName: \"noWaitOnDisconnected\",\n inQuorum: client !== undefined,\n hasTimer: this.prevClientLeftTimer.hasTimer,\n shouldClientJoinWrite: this.handler.shouldClientJoinWrite(),\n });\n }\n }\n\n // Report transition before we propagate event across layers\n this.handler.logConnectionStateChangeTelemetry(this._connectionState, oldState, reason);\n\n // Propagate event across layers\n this.handler.connectionStateChanged();\n }\n}\n"]}
1
+ {"version":3,"file":"connectionStateHandler.js","sourceRoot":"","sources":["../src/connectionStateHandler.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { IConnectionDetails } from \"@fluidframework/container-definitions\";\nimport { ProtocolOpHandler } from \"@fluidframework/protocol-base\";\nimport { ConnectionMode, ISequencedClient } from \"@fluidframework/protocol-definitions\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { assert, Timer } from \"@fluidframework/common-utils\";\nimport { ConnectionState } from \"./container\";\n\nexport interface IConnectionStateHandler {\n protocolHandler: () => ProtocolOpHandler | undefined,\n logConnectionStateChangeTelemetry:\n (value: ConnectionState, oldState: ConnectionState, reason?: string | undefined) => void,\n shouldClientJoinWrite: () => boolean,\n maxClientLeaveWaitTime: number | undefined,\n logConnectionIssue: (eventName: string) => void,\n connectionStateChanged: () => void,\n}\n\nexport interface ILocalSequencedClient extends ISequencedClient {\n shouldHaveLeft?: boolean;\n}\n\nconst JoinOpTimer = 45000;\n\nexport class ConnectionStateHandler {\n private _connectionState = ConnectionState.Disconnected;\n private _pendingClientId: string | undefined;\n private _clientId: string | undefined;\n private readonly prevClientLeftTimer: Timer;\n private readonly joinOpTimer: Timer;\n\n private waitEvent: PerformanceEvent | undefined;\n\n public get connectionState(): ConnectionState {\n return this._connectionState;\n }\n\n public get connected(): boolean {\n return this.connectionState === ConnectionState.Connected;\n }\n\n public get clientId(): string | undefined {\n return this._clientId;\n }\n\n public get pendingClientId(): string | undefined {\n return this._pendingClientId;\n }\n\n constructor(\n private readonly handler: IConnectionStateHandler,\n private readonly logger: ITelemetryLogger,\n ) {\n this.prevClientLeftTimer = new Timer(\n // Default is 5 min for which we are going to wait for its own \"leave\" message. This is same as\n // the max time on server after which leave op is sent.\n this.handler.maxClientLeaveWaitTime ?? 300000,\n () => {\n assert(!this.connected,\n 0x2ac /* \"Connected when timeout waiting for leave from previous session fired!\" */);\n this.applyForConnectedState(\"timeout\");\n },\n );\n\n // Based on recent data, it looks like majority of cases where we get stuck are due to really slow or\n // timing out ops fetches. So attempt recovery infrequently. Also fetch uses 30 second timeout, so\n // if retrying fixes the problem, we should not see these events.\n this.joinOpTimer = new Timer(\n JoinOpTimer,\n () => {\n // I've observed timer firing within couple ms from disconnect event, looks like\n // queued timer callback is not cancelled if timer is cancelled while callback sits in the queue.\n if (this.connectionState === ConnectionState.Connecting) {\n this.handler.logConnectionIssue(\"NoJoinOp\");\n }\n },\n );\n }\n\n private startJoinOpTimer() {\n assert(!this.joinOpTimer.hasTimer, 0x234 /* \"has joinOpTimer\" */);\n this.joinOpTimer.start();\n }\n\n private stopJoinOpTimer() {\n assert(this.joinOpTimer.hasTimer, 0x235 /* \"no joinOpTimer\" */);\n this.joinOpTimer.clear();\n }\n\n public dispose() {\n assert(!this.joinOpTimer.hasTimer, 0x2a5 /* \"join timer\" */);\n this.prevClientLeftTimer.clear();\n }\n\n public containerSaved() {\n // If we were waiting for moving to Connected state, then only apply for state change. Since the container\n // is now saved and we don't have any ops to roundtrip, we can clear the timer and apply for connected state.\n if (this.prevClientLeftTimer.hasTimer) {\n this.prevClientLeftTimer.clear();\n this.applyForConnectedState(\"containerSaved\");\n }\n }\n\n public receivedAddMemberEvent(clientId: string) {\n // This is the only one that requires the pending client ID\n if (clientId === this.pendingClientId) {\n if (this.joinOpTimer.hasTimer) {\n this.stopJoinOpTimer();\n } else {\n // timer has already fired, meaning it took too long to get join on.\n // Record how long it actually took to recover.\n this.handler.logConnectionIssue(\"ReceivedJoinOp\");\n }\n // Start the event in case we are waiting for leave or timeout.\n if (this.prevClientLeftTimer.hasTimer) {\n this.waitEvent = PerformanceEvent.start(this.logger, {\n eventName: \"WaitBeforeClientLeave\",\n waitOnClientId: this._clientId,\n hadOutstandingOps: this.handler.shouldClientJoinWrite(),\n });\n }\n this.applyForConnectedState(\"addMemberEvent\");\n }\n }\n\n private applyForConnectedState(source: \"removeMemberEvent\" | \"addMemberEvent\" | \"timeout\" | \"containerSaved\") {\n const protocolHandler = this.handler.protocolHandler();\n assert(protocolHandler !== undefined, 0x236 /* \"In all cases it should be already installed\" */);\n // Move to connected state only if we are in Connecting state, we have seen our join op\n // and there is no timer running which means we are not waiting for previous client to leave\n // or timeout has occured while doing so.\n if (this.pendingClientId !== this.clientId\n && this.pendingClientId !== undefined\n && protocolHandler.quorum.getMember(this.pendingClientId) !== undefined\n && !this.prevClientLeftTimer.hasTimer\n ) {\n this.waitEvent?.end({ source });\n this.setConnectionState(ConnectionState.Connected);\n } else {\n // Adding this event temporarily so that we can get help debugging if something goes wrong.\n this.logger.sendTelemetryEvent({\n eventName: \"connectedStateRejected\",\n category: source === \"timeout\" ? \"error\" : \"generic\",\n source,\n pendingClientId: this.pendingClientId,\n clientId: this.clientId,\n hasTimer: this.prevClientLeftTimer.hasTimer,\n inQuorum: protocolHandler !== undefined && this.pendingClientId !== undefined\n && protocolHandler.quorum.getMember(this.pendingClientId) !== undefined,\n });\n }\n }\n\n public receivedRemoveMemberEvent(clientId: string) {\n // If the client which has left was us, then finish the timer.\n if (this.clientId === clientId) {\n this.prevClientLeftTimer.clear();\n this.applyForConnectedState(\"removeMemberEvent\");\n }\n }\n\n public receivedDisconnectEvent(reason: string) {\n if (this.joinOpTimer.hasTimer) {\n this.stopJoinOpTimer();\n }\n this.setConnectionState(ConnectionState.Disconnected, reason);\n }\n\n public receivedConnectEvent(\n connectionMode: ConnectionMode,\n details: IConnectionDetails,\n ) {\n const oldState = this._connectionState;\n this._connectionState = ConnectionState.Connecting;\n\n // Stash the clientID to detect when transitioning from connecting (socket.io channel open) to connected\n // (have received the join message for the client ID)\n // This is especially important in the reconnect case. It's possible there could be outstanding\n // ops sent by this client, so we should keep the old client id until we see our own client's\n // join message. after we see the join message for out new connection with our new client id,\n // we know there can no longer be outstanding ops that we sent with the previous client id.\n this._pendingClientId = details.clientId;\n\n // Report telemetry after we set client id, but before transitioning to Connected state below!\n this.handler.logConnectionStateChangeTelemetry(ConnectionState.Connecting, oldState);\n\n const protocolHandler = this.handler.protocolHandler();\n // Check if we already processed our own join op through delta storage!\n // we are fetching ops from storage in parallel to connecting to ordering service\n // Given async processes, it's possible that we have already processed our own join message before\n // connection was fully established.\n // Note that we might be still initializing quorum - connection is established proactively on load!\n if ((protocolHandler !== undefined && protocolHandler.quorum.getMember(details.clientId) !== undefined)\n || connectionMode === \"read\"\n ) {\n assert(!this.prevClientLeftTimer.hasTimer, 0x2a6 /* \"there should be no timer for 'read' connections\" */);\n this.setConnectionState(ConnectionState.Connected);\n } else if (connectionMode === \"write\") {\n this.startJoinOpTimer();\n }\n }\n\n private setConnectionState(value: ConnectionState.Disconnected, reason: string);\n private setConnectionState(value: ConnectionState.Connected);\n private setConnectionState(value: ConnectionState, reason?: string) {\n if (this.connectionState === value) {\n // Already in the desired state - exit early\n this.logger.sendErrorEvent({ eventName: \"setConnectionStateSame\", value });\n return;\n }\n\n const oldState = this._connectionState;\n this._connectionState = value;\n const quorum = this.handler.protocolHandler()?.quorum;\n let client: ILocalSequencedClient | undefined;\n if (this._clientId !== undefined) {\n client = quorum?.getMember(this._clientId);\n }\n if (value === ConnectionState.Connected) {\n assert(oldState === ConnectionState.Connecting,\n 0x1d8 /* \"Should only transition from Connecting state\" */);\n // Mark our old client should have left in the quorum if it's still there\n if (client !== undefined) {\n client.shouldHaveLeft = true;\n }\n this._clientId = this.pendingClientId;\n } else if (value === ConnectionState.Disconnected) {\n // Important as we process our own joinSession message through delta request\n this._pendingClientId = undefined;\n // Only wait for \"leave\" message if the connected client exists in the quorum because only the write\n // client will exist in the quorum and only for those clients we will receive \"removeMember\" event and\n // the client has some unacked ops.\n // Also server would not accept ops from read client. Also check if the timer is not already running as\n // we could receive \"Disconnected\" event multiple times without getting connected and in that case we\n // don't want to reset the timer as we still want to wait on original client which started this timer.\n if (client !== undefined\n && this.handler.shouldClientJoinWrite()\n && this.prevClientLeftTimer.hasTimer === false\n ) {\n this.prevClientLeftTimer.restart();\n } else {\n // Adding this event temporarily so that we can get help debugging if something goes wrong.\n this.logger.sendTelemetryEvent({\n eventName: \"noWaitOnDisconnected\",\n inQuorum: client !== undefined,\n hasTimer: this.prevClientLeftTimer.hasTimer,\n shouldClientJoinWrite: this.handler.shouldClientJoinWrite(),\n });\n }\n }\n\n // Report transition before we propagate event across layers\n this.handler.logConnectionStateChangeTelemetry(this._connectionState, oldState, reason);\n\n // Propagate event across layers\n this.handler.connectionStateChanged();\n }\n}\n"]}
@@ -5,7 +5,7 @@
5
5
  import { IRequest, IResponse, IFluidRouter, IFluidCodeDetails } from "@fluidframework/core-interfaces";
6
6
  import { IAudience, IContainer, IContainerEvents, IDeltaManager, ICriticalContainerError, ContainerWarning, AttachState, ReadOnlyInfo, IContainerLoadMode } from "@fluidframework/container-definitions";
7
7
  import { IDocumentStorageService, IFluidResolvedUrl, IResolvedUrl } from "@fluidframework/driver-definitions";
8
- import { IClientConfiguration, IClientDetails, IDocumentMessage, IQuorum, ISequencedDocumentMessage, IVersion } from "@fluidframework/protocol-definitions";
8
+ import { IClientConfiguration, IClientDetails, IDocumentMessage, IQuorumClients, ISequencedDocumentMessage, IVersion } from "@fluidframework/protocol-definitions";
9
9
  import { EventEmitterWithErrorHandling, TelemetryLogger } from "@fluidframework/telemetry-utils";
10
10
  import { ILoaderOptions, Loader } from "./loader";
11
11
  export interface IContainerLoadOptions {
@@ -78,7 +78,7 @@ export declare class Container extends EventEmitterWithErrorHandling<IContainerE
78
78
  static rehydrateDetachedFromSnapshot(loader: Loader, snapshot: string): Promise<Container>;
79
79
  subLogger: TelemetryLogger;
80
80
  private readonly _canReconnect;
81
- private readonly logger;
81
+ private readonly mc;
82
82
  private _lifecycleState;
83
83
  private get loaded();
84
84
  private set loaded(value);
@@ -106,6 +106,7 @@ export declare class Container extends EventEmitterWithErrorHandling<IContainerE
106
106
  private attachStarted;
107
107
  private _dirtyContainer;
108
108
  private lastVisible;
109
+ private readonly visibilityEventHandler;
109
110
  private readonly connectionStateHandler;
110
111
  private setAutoReconnectTime;
111
112
  private readonly collabWindowTracker;
@@ -118,7 +119,6 @@ export declare class Container extends EventEmitterWithErrorHandling<IContainerE
118
119
  * Tracks host requiring read-only mode.
119
120
  */
120
121
  forceReadonly(readonly: boolean): void;
121
- get id(): string;
122
122
  get deltaManager(): IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;
123
123
  get connectionState(): ConnectionState;
124
124
  get connected(): boolean;
@@ -138,13 +138,6 @@ export declare class Container extends EventEmitterWithErrorHandling<IContainerE
138
138
  */
139
139
  get scopes(): string[] | undefined;
140
140
  get clientDetails(): IClientDetails;
141
- /**
142
- * The current code details for the container's runtime
143
- * @deprecated use getSpecifiedCodeDetails for the code details currently specified for this container, or
144
- * getLoadedCodeDetails for the code details that the container's context was loaded with.
145
- * To be removed after getSpecifiedCodeDetails and getLoadedCodeDetails become ubiquitous.
146
- */
147
- get codeDetails(): IFluidCodeDetails | undefined;
148
141
  /**
149
142
  * Get the code details that are currently specified for the container.
150
143
  * @returns The current code details if any are specified, undefined if none are specified.
@@ -168,14 +161,14 @@ export declare class Container extends EventEmitterWithErrorHandling<IContainerE
168
161
  get isDirty(): boolean;
169
162
  private get serviceFactory();
170
163
  private get urlResolver();
171
- get options(): ILoaderOptions;
164
+ readonly options: ILoaderOptions;
172
165
  private get scope();
173
166
  private get codeLoader();
174
167
  constructor(loader: Loader, config: IContainerConfig);
175
168
  /**
176
169
  * Retrieves the quorum associated with the document
177
170
  */
178
- getQuorum(): IQuorum;
171
+ getQuorum(): IQuorumClients;
179
172
  close(error?: ICriticalContainerError): void;
180
173
  closeAndGetPendingLocalState(): string;
181
174
  get attachState(): AttachState;
@@ -187,6 +180,7 @@ export declare class Container extends EventEmitterWithErrorHandling<IContainerE
187
180
  resume(): void;
188
181
  private resumeInternal;
189
182
  /**
183
+ * @deprecated 0.56, will be removed in next release from IContainerContext
190
184
  * Raise non-critical error to host. Calling this API will not close container.
191
185
  * For critical errors, please call Container.close(error).
192
186
  * @param error - an error to raise
@@ -1 +1 @@
1
- {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,OAAO,EACH,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,iBAAiB,EAEpB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACH,SAAS,EAET,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,uBAAuB,EACvB,gBAAgB,EAChB,WAAW,EAGX,YAAY,EACZ,kBAAkB,EACrB,MAAM,uCAAuC,CAAC;AAO/C,OAAO,EAEH,uBAAuB,EACvB,iBAAiB,EACjB,YAAY,EACf,MAAM,oCAAoC,CAAC;AAc5C,OAAO,EAGH,oBAAoB,EACpB,cAAc,EAGd,gBAAgB,EAGhB,cAAc,EAGd,yBAAyB,EASzB,QAAQ,EAIX,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAEH,6BAA6B,EAG7B,eAAe,EAMlB,MAAM,iCAAiC,CAAC;AAMzC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAkB,MAAM,UAAU,CAAC;AAgBlE,MAAM,WAAW,qBAAqB;IAClC;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,qBAAqB,CAAC,EAAE,cAAc,CAAC;IACvC,WAAW,EAAE,iBAAiB,CAAC;IAC/B;;OAEG;IACH,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B;;OAEG;IACH,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC7B,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,qBAAqB,CAAC,EAAE,cAAc,CAAC;CAC1C;AAED,oBAAY,eAAe;IACvB;;OAEG;IACH,YAAY,IAAA;IAEZ;;OAEG;IACH,UAAU,IAAA;IAEV;;OAEG;IACH,SAAS,IAAA;CACZ;AAED;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,UAAU,oBAmDjE;AAMD,qBAAa,SAAU,SAAQ,6BAA6B,CAAC,gBAAgB,CAAE,YAAW,UAAU;IAsS5F,OAAO,CAAC,QAAQ,CAAC,MAAM;IArS3B,OAAc,OAAO,SAAY;IAEjC;;OAEG;WACiB,IAAI,CACpB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,qBAAqB,EAClC,iBAAiB,CAAC,EAAE,OAAO,GAC5B,OAAO,CAAC,SAAS,CAAC;IAiDrB;;OAEG;WACiB,cAAc,CAC9B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,iBAAiB,GAC/B,OAAO,CAAC,SAAS,CAAC;IAgBrB;;;OAGG;WACiB,6BAA6B,CAC7C,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC,SAAS,CAAC;IAgBd,SAAS,EAAE,eAAe,CAAC;IAIlC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiB;IAE/C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;IAEvC,OAAO,CAAC,eAAe,CAAsE;IAE7F,OAAO,KAAK,MAAM,GAEjB;IAED,OAAO,KAAK,MAAM,QASjB;IAED,IAAW,MAAM,IAAI,OAAO,CAE3B;IAED,OAAO,CAAC,YAAY,CAAwB;IAE5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;IACnD,IAAW,OAAO,IAAI,uBAAuB,CAE5C;IAED,OAAO,CAAC,eAAe,CAAoD;IAC3E,OAAO,KAAK,cAAc,GAKzB;IAED,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA6B;IACnE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkC;IAChE,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IAErC,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,KAAK,OAAO,GAKlB;IACD,OAAO,CAAC,gBAAgB,CAAgC;IACxD,OAAO,KAAK,eAAe,GAK1B;IAED,OAAO,CAAC,4BAA4B,CAAS;IAC7C,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,yBAAyB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAgB;IAC1D,OAAO,CAAC,8BAA8B,CAAa;IACnD,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,YAAY,CAAgC;IACpD,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,eAAe,CAAS;IAEhC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA2B;IAClE,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAyB;IAEhE,OAAO,CAAC,oBAAoB,CAAqB;IAEjD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAKlC;IAEF,OAAO,KAAK,cAAc,GAAkE;IAE5F,IAAW,YAAY,IAAI,YAAY,CAAiB;IAExD,IAAW,WAAW,IAAI,YAAY,GAAG,SAAS,CAEjD;IAED,IAAW,iBAAiB,IAAI,QAAQ,GAAG,SAAS,CAEnD;IAED,IAAW,YAAY,IAAI,YAAY,CAEtC;IAED;;OAEG;IACI,aAAa,CAAC,QAAQ,EAAE,OAAO;IAItC,IAAW,YAAY,IAAI,aAAa,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,CAEpF;IAED,IAAW,eAAe,IAAI,eAAe,CAE5C;IAED,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED;;;OAGG;IACH,IAAW,oBAAoB,IAAI,oBAAoB,GAAG,SAAS,CAElE;IAED;;;OAGG;IACH,IAAW,QAAQ,IAAI,MAAM,GAAG,SAAS,CAExC;IAED;;;OAGG;IACH,IAAW,MAAM,IAAI,MAAM,EAAE,GAAG,SAAS,CAExC;IAED,IAAW,aAAa,IAAI,cAAc,CAEzC;IAED;;;OAGG;IACI,uBAAuB,IAAI,iBAAiB,GAAG,SAAS;IAI/D;;;;OAIG;IACI,oBAAoB,IAAI,iBAAiB,GAAG,SAAS;IAI5D;;OAEG;IACH,IAAW,QAAQ,IAAI,SAAS,CAE/B;IAED;;;;OAIG;IACH,IAAW,OAAO,YAEjB;IAED,OAAO,KAAK,cAAc,GAAwD;IAClF,OAAO,KAAK,WAAW,GAA6C;IACpE,SAAgB,OAAO,EAAE,cAAc,CAAC;IACxC,OAAO,KAAK,KAAK,GAAwC;IACzD,OAAO,KAAK,UAAU,GAA6C;gBAG9C,MAAM,EAAE,MAAM,EAC/B,MAAM,EAAE,gBAAgB;IAqK5B;;OAEG;IACI,SAAS,IAAI,cAAc;IAI3B,KAAK,CAAC,KAAK,CAAC,EAAE,uBAAuB;IAkDrC,4BAA4B,IAAI,MAAM;IAkB7C,IAAW,WAAW,IAAI,WAAW,CAEpC;IAEM,SAAS,IAAI,MAAM;IAab,MAAM,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA8GxC,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAS3C,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB5E,gBAAgB,CAAC,SAAS,EAAE,OAAO;IAqCnC,MAAM;IASb,OAAO,CAAC,cAAc;IActB;;;;;OAKG;IACI,qBAAqB,CAAC,OAAO,EAAE,gBAAgB;IASzC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAWhE,kBAAkB,CAAC,WAAW,EAAE,iBAAiB;YAmBhD,mBAAmB;YAgBnB,YAAY;IAwB1B,OAAO,CAAC,YAAY;YAwDN,UAAU;IAKxB,OAAO,CAAC,sBAAsB;IAM9B,OAAO,CAAC,oBAAoB;IAW5B;;;;;;OAMG;YACW,IAAI;YAuHJ,cAAc;YAuCd,6BAA6B;YA4B7B,qBAAqB;YAsBrB,qBAAqB;YA2BrB,8BAA8B;YA2B9B,uBAAuB;IAwDrC,OAAO,CAAC,sBAAsB;IAmC9B,OAAO,CAAC,wBAAwB;IAQhC,OAAO,KAAK,MAAM,GAkBjB;IAED;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,kBAAkB;YAuDZ,2BAA2B;IAiBzC,OAAO,CAAC,iCAAiC;IA4DzC,OAAO,CAAC,wBAAwB;IAuBhC,OAAO,CAAC,sBAAsB;IA4B9B,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,oBAAoB;IAoC5B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,aAAa;IAiBrB;;;;OAIG;YACW,iBAAiB;YAkBjB,0BAA0B;YAkB1B,kBAAkB;IAwChC,OAAO,CAAC,iBAAiB;CAG5B"}
package/dist/container.js CHANGED
@@ -111,9 +111,9 @@ const getCodeProposal =
111
111
  (quorum) => { var _a; return (_a = quorum.get("code")) !== null && _a !== void 0 ? _a : quorum.get("code2"); };
112
112
  class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
113
113
  constructor(loader, config) {
114
- var _a, _b;
114
+ var _a, _b, _c;
115
115
  super((name, error) => {
116
- this.logger.sendErrorEvent({
116
+ this.mc.logger.sendErrorEvent({
117
117
  eventName: "ContainerEventHandlerException",
118
118
  name: typeof name === "string" ? name : undefined,
119
119
  }, error);
@@ -149,12 +149,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
149
149
  all: {
150
150
  clientType,
151
151
  containerId: uuid_1.v4(),
152
- docId: () => this.id,
152
+ docId: () => { var _a, _b; return (_b = (_a = this._resolvedUrl) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : undefined; },
153
153
  containerAttachState: () => this._attachState,
154
154
  containerLifecycleState: () => this._lifecycleState,
155
155
  containerConnectionState: () => ConnectionState[this.connectionState],
156
156
  },
157
- // we need to be judicious with our logging here to avoid generting too much data
157
+ // we need to be judicious with our logging here to avoid generating too much data
158
158
  // all data logged here should be broadly applicable, and not specific to a
159
159
  // specific error or class of errors
160
160
  error: {
@@ -167,12 +167,13 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
167
167
  dmLastMsqSeqNumber: () => { var _a, _b; return (_b = (_a = this.deltaManager) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.sequenceNumber; },
168
168
  dmLastMsqSeqTimestamp: () => { var _a, _b; return (_b = (_a = this.deltaManager) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.timestamp; },
169
169
  dmLastMsqSeqClientId: () => { var _a, _b; return (_b = (_a = this.deltaManager) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.clientId; },
170
- connectionState: () => ConnectionState[this.connectionState],
171
170
  connectionStateDuration: () => common_utils_1.performance.now() - this.connectionTransitionTimes[this.connectionState],
172
171
  },
173
172
  });
174
173
  // Prefix all events in this file with container-loader
175
- this.logger = telemetry_utils_1.ChildLogger.create(this.subLogger, "Container");
174
+ this.mc = telemetry_utils_1.loggerToMonitoringContext(telemetry_utils_1.ChildLogger.create(this.subLogger, "Container"));
175
+ const summarizeProtocolTree = (_c = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree")) !== null && _c !== void 0 ? _c : this.loader.services.options.summarizeProtocolTree;
176
+ this.options = Object.assign(Object.assign({}, this.loader.services.options), { summarizeProtocolTree });
176
177
  this.connectionStateHandler = new connectionStateHandler_1.ConnectionStateHandler({
177
178
  protocolHandler: () => this._protocolHandler,
178
179
  logConnectionStateChangeTelemetry: (value, oldState, reason) => this.logConnectionStateChangeTelemetry(value, oldState, reason),
@@ -191,14 +192,17 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
191
192
  this.propagateConnectionState();
192
193
  }
193
194
  },
194
- }, this.logger);
195
+ }, this.mc.logger);
196
+ this.on(savedContainerEvent, () => {
197
+ this.connectionStateHandler.containerSaved();
198
+ });
195
199
  this._deltaManager = this.createDeltaManager();
196
200
  this._storage = new containerStorageAdapter_1.ContainerStorageAdapter(() => {
197
201
  if (this.attachState !== container_definitions_1.AttachState.Attached) {
198
202
  if (this.loader.services.detachedBlobStorage !== undefined) {
199
- return new containerStorageAdapter_1.BlobOnlyStorage(this.loader.services.detachedBlobStorage, this.logger);
203
+ return new containerStorageAdapter_1.BlobOnlyStorage(this.loader.services.detachedBlobStorage, this.mc.logger);
200
204
  }
201
- this.logger.sendErrorEvent({
205
+ this.mc.logger.sendErrorEvent({
202
206
  eventName: "NoRealStorageInDetachedContainer",
203
207
  });
204
208
  throw new Error("Real storage calls not allowed in Unattached container");
@@ -212,7 +216,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
212
216
  // keep track of last time page was visible for telemetry
213
217
  if (isDomAvailable) {
214
218
  this.lastVisible = document.hidden ? common_utils_1.performance.now() : undefined;
215
- document.addEventListener("visibilitychange", () => {
219
+ this.visibilityEventHandler = () => {
216
220
  if (document.hidden) {
217
221
  this.lastVisible = common_utils_1.performance.now();
218
222
  }
@@ -220,7 +224,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
220
224
  // settimeout so this will hopefully fire after disconnect event if being hidden caused it
221
225
  setTimeout(() => this.lastVisible = undefined, 0);
222
226
  }
223
- });
227
+ };
228
+ document.addEventListener("visibilitychange", this.visibilityEventHandler);
224
229
  }
225
230
  // We observed that most users of platform do not check Container.connected event on load, causing bugs.
226
231
  // As such, we are raising events when new listener pops up.
@@ -253,7 +258,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
253
258
  default:
254
259
  }
255
260
  }).catch((error) => {
256
- this.logger.sendErrorEvent({ eventName: "RaiseConnectedEventError" }, error);
261
+ this.mc.logger.sendErrorEvent({ eventName: "RaiseConnectedEventError" }, error);
257
262
  });
258
263
  });
259
264
  }
@@ -266,7 +271,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
266
271
  resolvedUrl: loadOptions.resolvedUrl,
267
272
  canReconnect: loadOptions.canReconnect,
268
273
  });
269
- return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.logger, { eventName: "Load" }, async (event) => new Promise((res, rej) => {
274
+ return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "Load" }, async (event) => new Promise((resolve, reject) => {
270
275
  var _a;
271
276
  container._lifecycleState = "loading";
272
277
  const version = loadOptions.version;
@@ -276,7 +281,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
276
281
  common_utils_1.assert(pendingLocalState === undefined || loadOptions.loadMode === undefined, 0x1e1 /* "pending state requires immediate connection!" */);
277
282
  const mode = (_a = loadOptions.loadMode) !== null && _a !== void 0 ? _a : defaultMode;
278
283
  const onClosed = (err) => {
279
- rej(err !== null && err !== void 0 ? err : new container_utils_1.GenericError("containerClosedWithoutErrorDuringLoad"));
284
+ reject(err !== null && err !== void 0 ? err : new container_utils_1.GenericError("containerClosedWithoutErrorDuringLoad"));
280
285
  };
281
286
  container.on("closed", onClosed);
282
287
  container.load(version, mode, pendingLocalState)
@@ -285,7 +290,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
285
290
  })
286
291
  .then((props) => {
287
292
  event.end(Object.assign(Object.assign({}, props), loadOptions.loadMode));
288
- res(container);
293
+ resolve(container);
289
294
  }, (error) => {
290
295
  const err = telemetry_utils_1.normalizeError(error);
291
296
  // Depending where error happens, we can be attempting to connect to web socket
@@ -301,7 +306,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
301
306
  */
302
307
  static async createDetached(loader, codeDetails) {
303
308
  const container = new Container(loader, {});
304
- return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.logger, { eventName: "CreateDetached" }, async (_event) => {
309
+ return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "CreateDetached" }, async (_event) => {
305
310
  container._lifecycleState = "loading";
306
311
  await container.createDetached(codeDetails);
307
312
  return container;
@@ -313,7 +318,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
313
318
  */
314
319
  static async rehydrateDetachedFromSnapshot(loader, snapshot) {
315
320
  const container = new Container(loader, {});
316
- return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.logger, { eventName: "RehydrateDetachedFromSnapshot" }, async (_event) => {
321
+ return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "RehydrateDetachedFromSnapshot" }, async (_event) => {
317
322
  const deserializedSummary = JSON.parse(snapshot);
318
323
  container._lifecycleState = "loading";
319
324
  await container.rehydrateDetachedFromSnapshot(deserializedSummary);
@@ -373,10 +378,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
373
378
  forceReadonly(readonly) {
374
379
  this._deltaManager.connectionManager.forceReadonly(readonly);
375
380
  }
376
- get id() {
377
- var _a, _b;
378
- return (_b = (_a = this._resolvedUrl) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : "";
379
- }
380
381
  get deltaManager() {
381
382
  return this._deltaManager;
382
383
  }
@@ -410,16 +411,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
410
411
  get clientDetails() {
411
412
  return this._deltaManager.clientDetails;
412
413
  }
413
- /**
414
- * The current code details for the container's runtime
415
- * @deprecated use getSpecifiedCodeDetails for the code details currently specified for this container, or
416
- * getLoadedCodeDetails for the code details that the container's context was loaded with.
417
- * To be removed after getSpecifiedCodeDetails and getLoadedCodeDetails become ubiquitous.
418
- */
419
- get codeDetails() {
420
- var _a, _b;
421
- return (_b = (_a = this._context) === null || _a === void 0 ? void 0 : _a.codeDetails) !== null && _b !== void 0 ? _b : this.getCodeDetailsFromQuorum();
422
- }
423
414
  /**
424
415
  * Get the code details that are currently specified for the container.
425
416
  * @returns The current code details if any are specified, undefined if none are specified.
@@ -452,7 +443,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
452
443
  }
453
444
  get serviceFactory() { return this.loader.services.documentServiceFactory; }
454
445
  get urlResolver() { return this.loader.services.urlResolver; }
455
- get options() { return this.loader.services.options; }
456
446
  get scope() { return this.loader.services.scope; }
457
447
  get codeLoader() { return this.loader.services.codeLoader; }
458
448
  /**
@@ -482,14 +472,17 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
482
472
  (_d = this.service) === null || _d === void 0 ? void 0 : _d.dispose(error);
483
473
  }
484
474
  catch (exception) {
485
- this.logger.sendErrorEvent({ eventName: "ContainerCloseException" }, exception);
475
+ this.mc.logger.sendErrorEvent({ eventName: "ContainerCloseException" }, exception);
486
476
  }
487
- this.logger.sendTelemetryEvent({
477
+ this.mc.logger.sendTelemetryEvent({
488
478
  eventName: "ContainerClose",
489
479
  category: error === undefined ? "generic" : "error",
490
480
  }, error);
491
481
  this.emit("closed", error);
492
482
  this.removeAllListeners();
483
+ if (this.visibilityEventHandler !== undefined) {
484
+ document.removeEventListener("visibilitychange", this.visibilityEventHandler);
485
+ }
493
486
  }
494
487
  finally {
495
488
  this._lifecycleState = "closed";
@@ -522,7 +515,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
522
515
  return JSON.stringify(combinedSummary);
523
516
  }
524
517
  async attach(request) {
525
- await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.logger, { eventName: "Attach" }, async () => {
518
+ await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Attach" }, async () => {
526
519
  if (this._lifecycleState !== "loaded") {
527
520
  throw new container_utils_1.UsageError(`containerNotValidForAttach [${this._lifecycleState}]`);
528
521
  }
@@ -552,7 +545,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
552
545
  const createNewResolvedUrl = await this.urlResolver.resolve(request);
553
546
  driver_utils_1.ensureFluidResolvedUrl(createNewResolvedUrl);
554
547
  if (this.service === undefined) {
555
- this.service = await driver_utils_1.runWithRetry(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger), "containerAttach", this.logger, {});
548
+ this.service = await driver_utils_1.runWithRetry(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger), "containerAttach", this.mc.logger, {});
556
549
  }
557
550
  const resolvedUrl = this.service.resolvedUrl;
558
551
  driver_utils_1.ensureFluidResolvedUrl(resolvedUrl);
@@ -606,12 +599,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
606
599
  }, { start: true, end: true, cancel: "generic" });
607
600
  }
608
601
  async request(path) {
609
- return telemetry_utils_1.PerformanceEvent.timedExecAsync(this.logger, { eventName: "Request" }, async () => this.context.request(path), { end: true, cancel: "error" });
602
+ return telemetry_utils_1.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Request" }, async () => this.context.request(path), { end: true, cancel: "error" });
610
603
  }
611
604
  async snapshot(tagMessage, fullTree = false) {
612
605
  // Only snapshot once a code quorum has been established
613
606
  if (!this.protocolHandler.quorum.has("code") && !this.protocolHandler.quorum.has("code2")) {
614
- this.logger.sendTelemetryEvent({ eventName: "SkipSnapshot" });
607
+ this.mc.logger.sendTelemetryEvent({ eventName: "SkipSnapshot" });
615
608
  return;
616
609
  }
617
610
  // Stop inbound message processing while we complete the snapshot
@@ -620,7 +613,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
620
613
  await this.snapshotCore(tagMessage, fullTree);
621
614
  }
622
615
  catch (ex) {
623
- this.logger.sendErrorEvent({ eventName: "SnapshotExceptionError" }, ex);
616
+ this.mc.logger.sendErrorEvent({ eventName: "SnapshotExceptionError" }, ex);
624
617
  throw ex;
625
618
  }
626
619
  finally {
@@ -639,7 +632,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
639
632
  const now = common_utils_1.performance.now();
640
633
  const duration = now - this.setAutoReconnectTime;
641
634
  this.setAutoReconnectTime = now;
642
- this.logger.sendTelemetryEvent({
635
+ this.mc.logger.sendTelemetryEvent({
643
636
  eventName: reconnect ? "AutoReconnectEnabled" : "AutoReconnectDisabled",
644
637
  connectionMode: this.connectionMode,
645
638
  connectionState: ConnectionState[this.connectionState],
@@ -677,6 +670,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
677
670
  this.connectToDeltaStream(args);
678
671
  }
679
672
  /**
673
+ * @deprecated 0.56, will be removed in next release from IContainerContext
680
674
  * Raise non-critical error to host. Calling this API will not close container.
681
675
  * For critical errors, please call Container.close(error).
682
676
  * @param error - an error to raise
@@ -701,12 +695,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
701
695
  throw new Error("Provided codeDetails are not IFluidCodeDetails");
702
696
  }
703
697
  if (this.codeLoader.IFluidCodeDetailsComparer) {
704
- const comparision = await this.codeLoader.IFluidCodeDetailsComparer.compare(codeDetails, this.getCodeDetailsFromQuorum());
705
- if (comparision !== undefined && comparision <= 0) {
698
+ const comparison = await this.codeLoader.IFluidCodeDetailsComparer.compare(codeDetails, this.getCodeDetailsFromQuorum());
699
+ if (comparison !== undefined && comparison <= 0) {
706
700
  throw new Error("Proposed code details should be greater than the current");
707
701
  }
708
702
  }
709
- return this.getQuorum().propose("code", codeDetails)
703
+ return this.protocolHandler.quorum.propose("code", codeDetails)
710
704
  .then(() => true)
711
705
  .catch(() => false);
712
706
  }
@@ -735,7 +729,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
735
729
  const deltaDetails = `${this._deltaManager.lastSequenceNumber}:${this._deltaManager.minimumSequenceNumber}`;
736
730
  const message = `Commit @${deltaDetails} ${tagMessage}`;
737
731
  // Pull in the prior version and snapshot tree to store against
738
- const lastVersion = await this.getVersion(this.id);
732
+ const lastVersion = await this.getVersion(null);
739
733
  const parents = lastVersion !== undefined ? [lastVersion.id] : [];
740
734
  // Write the full snapshot
741
735
  return this.storageService.write(root, parents, message, "");
@@ -772,7 +766,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
772
766
  });
773
767
  // Save attributes for the document
774
768
  const documentAttributes = {
775
- branch: this.id,
776
769
  minimumSequenceNumber: this._deltaManager.minimumSequenceNumber,
777
770
  sequenceNumber: this._deltaManager.lastSequenceNumber,
778
771
  term: this._deltaManager.referenceTerm,
@@ -961,8 +954,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
961
954
  common_utils_1.assert(this.service !== undefined, 0x1ef /* "services must be defined" */);
962
955
  const storageService = await this.service.connectToStorage();
963
956
  this._storageService =
964
- new retriableDocumentStorageService_1.RetriableDocumentStorageService(storageService, this.logger);
957
+ new retriableDocumentStorageService_1.RetriableDocumentStorageService(storageService, this.mc.logger);
965
958
  if (this.options.summarizeProtocolTree === true) {
959
+ this.mc.logger.sendTelemetryEvent({ eventName: "summarizeProtocolTreeEnabled" });
966
960
  this._storageService =
967
961
  new protocolTreeDocumentStorageService_1.ProtocolTreeStorageService(this._storageService, () => this.captureProtocolSummary());
968
962
  }
@@ -1024,7 +1018,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1024
1018
  protocol.quorum.on("approveProposal", (sequenceNumber, key, value) => {
1025
1019
  if (key === "code" || key === "code2") {
1026
1020
  if (!core_interfaces_1.isFluidCodeDetails(value)) {
1027
- this.logger.sendErrorEvent({
1021
+ this.mc.logger.sendErrorEvent({
1028
1022
  eventName: "CodeProposalNotIFluidCodeDetails",
1029
1023
  });
1030
1024
  }
@@ -1178,7 +1172,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1178
1172
  connectionInitiationReason = "AutoReconnect";
1179
1173
  }
1180
1174
  }
1181
- this.logger.sendPerformanceEvent(Object.assign({ eventName: `ConnectionStateChange_${ConnectionState[value]}`, from: ConnectionState[oldState], duration,
1175
+ this.mc.logger.sendPerformanceEvent(Object.assign({ eventName: `ConnectionStateChange_${ConnectionState[value]}`, from: ConnectionState[oldState], duration,
1182
1176
  durationFromDisconnected,
1183
1177
  reason,
1184
1178
  connectionInitiationReason, pendingClientId: this.connectionStateHandler.pendingClientId, clientId: this.clientId, autoReconnect,
@@ -1201,9 +1195,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1201
1195
  }
1202
1196
  common_utils_1.assert(this.protocolHandler !== undefined, 0x0dc /* "Protocol handler should be set here" */);
1203
1197
  this.protocolHandler.quorum.setConnectionState(state, this.clientId);
1204
- telemetry_utils_1.raiseConnectedEvent(this.logger, this, state, this.clientId);
1198
+ telemetry_utils_1.raiseConnectedEvent(this.mc.logger, this, state, this.clientId);
1205
1199
  if (logOpsOnReconnect) {
1206
- this.logger.sendTelemetryEvent({ eventName: "OpsSentOnReconnect", count: this.messageCountAfterDisconnection });
1200
+ this.mc.logger.sendTelemetryEvent({ eventName: "OpsSentOnReconnect", count: this.messageCountAfterDisconnection });
1207
1201
  }
1208
1202
  }
1209
1203
  submitContainerMessage(type, contents, batch, metadata) {
@@ -1233,7 +1227,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1233
1227
  }
1234
1228
  submitMessage(type, contents, batch, metadata) {
1235
1229
  if (this.connectionState !== ConnectionState.Connected) {
1236
- this.logger.sendErrorEvent({ eventName: "SubmitMessageWithNoConnection", type });
1230
+ this.mc.logger.sendErrorEvent({ eventName: "SubmitMessageWithNoConnection", type });
1237
1231
  return -1;
1238
1232
  }
1239
1233
  this.messageCountAfterDisconnection += 1;
@@ -1296,15 +1290,15 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1296
1290
  */
1297
1291
  async fetchSnapshotTree(specifiedVersion) {
1298
1292
  var _a;
1299
- const version = await this.getVersion(specifiedVersion !== null && specifiedVersion !== void 0 ? specifiedVersion : this.id);
1293
+ const version = await this.getVersion(specifiedVersion !== null && specifiedVersion !== void 0 ? specifiedVersion : null);
1300
1294
  if (version === undefined && specifiedVersion !== undefined) {
1301
1295
  // We should have a defined version to load from if specified version requested
1302
- this.logger.sendErrorEvent({ eventName: "NoVersionFoundWhenSpecified", id: specifiedVersion });
1296
+ this.mc.logger.sendErrorEvent({ eventName: "NoVersionFoundWhenSpecified", id: specifiedVersion });
1303
1297
  }
1304
1298
  this._loadedFromVersion = version;
1305
1299
  const snapshot = (_a = await this.storageService.getSnapshotTree(version)) !== null && _a !== void 0 ? _a : undefined;
1306
1300
  if (snapshot === undefined && version !== undefined) {
1307
- this.logger.sendErrorEvent({ eventName: "getSnapshotTreeFailed", id: version.id });
1301
+ this.mc.logger.sendErrorEvent({ eventName: "getSnapshotTreeFailed", id: version.id });
1308
1302
  }
1309
1303
  return { snapshot, versionId: version === null || version === void 0 ? void 0 : version.id };
1310
1304
  }
@@ -1320,7 +1314,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1320
1314
  common_utils_1.assert(((_a = this._context) === null || _a === void 0 ? void 0 : _a.disposed) !== false, 0x0dd /* "Existing context not disposed" */);
1321
1315
  // If this assert fires, our state tracking is likely not synchronized between COntainer & runtime.
1322
1316
  if (this._dirtyContainer) {
1323
- this.logger.sendErrorEvent({ eventName: "DirtyContainerReloadContainer" });
1317
+ this.mc.logger.sendErrorEvent({ eventName: "DirtyContainerReloadContainer" });
1324
1318
  }
1325
1319
  // The relative loader will proxy requests to '/' to the loader itself assuming no non-cache flags
1326
1320
  // are set. Global requests will still go directly to the loader
@@ -1331,10 +1325,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1331
1325
  }, existing, pendingLocalState);
1332
1326
  this.emit("contextChanged", codeDetails);
1333
1327
  }
1334
- // Please avoid calling it directly.
1335
- // raiseContainerWarning() is the right flow for most cases
1336
1328
  logContainerError(warning) {
1337
- this.logger.sendErrorEvent({ eventName: "ContainerWarning" }, warning);
1329
+ this.mc.logger.sendErrorEvent({ eventName: "ContainerWarning" }, warning);
1338
1330
  }
1339
1331
  }
1340
1332
  exports.Container = Container;