@fluidframework/odsp-driver 0.58.1001 → 0.58.2001

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 (117) hide show
  1. package/dist/createFile.d.ts.map +1 -1
  2. package/dist/createFile.js +6 -2
  3. package/dist/createFile.js.map +1 -1
  4. package/dist/fetchSnapshot.js +1 -1
  5. package/dist/fetchSnapshot.js.map +1 -1
  6. package/dist/getFileLink.d.ts.map +1 -1
  7. package/dist/getFileLink.js +8 -5
  8. package/dist/getFileLink.js.map +1 -1
  9. package/dist/getSocketIo.d.ts +2 -2
  10. package/dist/getSocketIo.d.ts.map +1 -1
  11. package/dist/getSocketIo.js.map +1 -1
  12. package/dist/odspCache.d.ts +4 -1
  13. package/dist/odspCache.d.ts.map +1 -1
  14. package/dist/odspCache.js +25 -36
  15. package/dist/odspCache.js.map +1 -1
  16. package/dist/odspDocumentDeltaConnection.d.ts +2 -2
  17. package/dist/odspDocumentDeltaConnection.d.ts.map +1 -1
  18. package/dist/odspDocumentDeltaConnection.js.map +1 -1
  19. package/dist/odspDocumentService.d.ts +7 -6
  20. package/dist/odspDocumentService.d.ts.map +1 -1
  21. package/dist/odspDocumentService.js +24 -15
  22. package/dist/odspDocumentService.js.map +1 -1
  23. package/dist/odspDocumentServiceFactoryCore.d.ts +2 -2
  24. package/dist/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  25. package/dist/odspDocumentServiceFactoryCore.js +13 -3
  26. package/dist/odspDocumentServiceFactoryCore.js.map +1 -1
  27. package/dist/odspDriverUrlResolver.js.map +1 -1
  28. package/dist/odspDriverUrlResolverForShareLink.d.ts +0 -1
  29. package/dist/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  30. package/dist/odspDriverUrlResolverForShareLink.js +1 -16
  31. package/dist/odspDriverUrlResolverForShareLink.js.map +1 -1
  32. package/dist/odspError.d.ts.map +1 -1
  33. package/dist/odspError.js +1 -0
  34. package/dist/odspError.js.map +1 -1
  35. package/dist/odspUtils.d.ts +2 -2
  36. package/dist/odspUtils.d.ts.map +1 -1
  37. package/dist/odspUtils.js +20 -8
  38. package/dist/odspUtils.js.map +1 -1
  39. package/dist/packageVersion.d.ts +1 -1
  40. package/dist/packageVersion.js +1 -1
  41. package/dist/packageVersion.js.map +1 -1
  42. package/dist/prefetchLatestSnapshot.d.ts.map +1 -1
  43. package/dist/prefetchLatestSnapshot.js +6 -1
  44. package/dist/prefetchLatestSnapshot.js.map +1 -1
  45. package/dist/retryErrorsStorageAdapter.d.ts.map +1 -1
  46. package/dist/retryErrorsStorageAdapter.js +1 -0
  47. package/dist/retryErrorsStorageAdapter.js.map +1 -1
  48. package/dist/vroom.d.ts.map +1 -1
  49. package/dist/vroom.js +3 -2
  50. package/dist/vroom.js.map +1 -1
  51. package/lib/createFile.d.ts.map +1 -1
  52. package/lib/createFile.js +6 -2
  53. package/lib/createFile.js.map +1 -1
  54. package/lib/fetchSnapshot.js +1 -1
  55. package/lib/fetchSnapshot.js.map +1 -1
  56. package/lib/getFileLink.d.ts.map +1 -1
  57. package/lib/getFileLink.js +9 -6
  58. package/lib/getFileLink.js.map +1 -1
  59. package/lib/getSocketIo.d.ts +2 -2
  60. package/lib/getSocketIo.d.ts.map +1 -1
  61. package/lib/getSocketIo.js.map +1 -1
  62. package/lib/odspCache.d.ts +4 -1
  63. package/lib/odspCache.d.ts.map +1 -1
  64. package/lib/odspCache.js +23 -34
  65. package/lib/odspCache.js.map +1 -1
  66. package/lib/odspDocumentDeltaConnection.d.ts +2 -2
  67. package/lib/odspDocumentDeltaConnection.d.ts.map +1 -1
  68. package/lib/odspDocumentDeltaConnection.js.map +1 -1
  69. package/lib/odspDocumentService.d.ts +7 -6
  70. package/lib/odspDocumentService.d.ts.map +1 -1
  71. package/lib/odspDocumentService.js +25 -16
  72. package/lib/odspDocumentService.js.map +1 -1
  73. package/lib/odspDocumentServiceFactoryCore.d.ts +2 -2
  74. package/lib/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  75. package/lib/odspDocumentServiceFactoryCore.js +13 -3
  76. package/lib/odspDocumentServiceFactoryCore.js.map +1 -1
  77. package/lib/odspDriverUrlResolver.js.map +1 -1
  78. package/lib/odspDriverUrlResolverForShareLink.d.ts +0 -1
  79. package/lib/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  80. package/lib/odspDriverUrlResolverForShareLink.js +1 -16
  81. package/lib/odspDriverUrlResolverForShareLink.js.map +1 -1
  82. package/lib/odspError.d.ts.map +1 -1
  83. package/lib/odspError.js +1 -0
  84. package/lib/odspError.js.map +1 -1
  85. package/lib/odspUtils.d.ts +2 -2
  86. package/lib/odspUtils.d.ts.map +1 -1
  87. package/lib/odspUtils.js +20 -8
  88. package/lib/odspUtils.js.map +1 -1
  89. package/lib/packageVersion.d.ts +1 -1
  90. package/lib/packageVersion.js +1 -1
  91. package/lib/packageVersion.js.map +1 -1
  92. package/lib/prefetchLatestSnapshot.d.ts.map +1 -1
  93. package/lib/prefetchLatestSnapshot.js +6 -1
  94. package/lib/prefetchLatestSnapshot.js.map +1 -1
  95. package/lib/retryErrorsStorageAdapter.d.ts.map +1 -1
  96. package/lib/retryErrorsStorageAdapter.js +1 -0
  97. package/lib/retryErrorsStorageAdapter.js.map +1 -1
  98. package/lib/vroom.d.ts.map +1 -1
  99. package/lib/vroom.js +3 -2
  100. package/lib/vroom.js.map +1 -1
  101. package/package.json +13 -10
  102. package/src/createFile.ts +2 -0
  103. package/src/fetchSnapshot.ts +1 -1
  104. package/src/getFileLink.ts +23 -6
  105. package/src/getSocketIo.ts +1 -1
  106. package/src/odspCache.ts +43 -57
  107. package/src/odspDocumentDeltaConnection.ts +6 -5
  108. package/src/odspDocumentService.ts +52 -25
  109. package/src/odspDocumentServiceFactoryCore.ts +16 -4
  110. package/src/odspDriverUrlResolver.ts +4 -4
  111. package/src/odspDriverUrlResolverForShareLink.ts +5 -31
  112. package/src/odspError.ts +1 -0
  113. package/src/odspUtils.ts +9 -4
  114. package/src/packageVersion.ts +1 -1
  115. package/src/prefetchLatestSnapshot.ts +7 -1
  116. package/src/retryErrorsStorageAdapter.ts +1 -0
  117. package/src/vroom.ts +10 -3
@@ -1 +1 @@
1
- {"version":3,"file":"odspCache.js","sourceRoot":"","sources":["../src/odspCache.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 { PromiseCache } from \"@fluidframework/common-utils\";\nimport {\n IOdspResolvedUrl,\n IFileEntry,\n IEntry,\n IPersistedCache,\n ICacheEntry,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISocketStorageDiscovery } from \"./contracts\";\n/**\n * Similar to IPersistedCache, but exposes cache interface for single file\n */\nexport interface IPersistedFileCache {\n get(entry: IEntry): Promise<any>;\n put(entry: IEntry, value: any): Promise<void>;\n removeEntries(): Promise<void>;\n}\n\n/**\n * Handles garbage collection of expiring cache entries.\n * Not exported.\n * (Based off of the same class in promiseCache.ts, could be consolidated)\n */\nclass GarbageCollector<TKey> {\n private readonly gcTimeouts = new Map<TKey, ReturnType<typeof setTimeout>>();\n\n constructor(\n private readonly cleanup: (key: TKey) => void,\n ) { }\n\n /**\n * Schedule GC for the given key, as applicable\n */\n public schedule(key: TKey, durationMs: number) {\n this.gcTimeouts.set(\n key,\n setTimeout(\n () => { this.cleanup(key); this.cancel(key); },\n durationMs,\n ),\n );\n }\n\n /**\n * Cancel any pending GC for the given key\n */\n public cancel(key: TKey) {\n const timeout = this.gcTimeouts.get(key);\n if (timeout !== undefined) {\n clearTimeout(timeout);\n this.gcTimeouts.delete(key);\n }\n }\n}\n\n/**\n * Default local-only implementation of IPersistedCache,\n * used if no persisted cache is provided by the host\n */\nexport class LocalPersistentCache implements IPersistedCache {\n private readonly cache = new Map<string, any>();\n private readonly gc = new GarbageCollector<string>((key) => this.cache.delete(key));\n\n public constructor(private readonly snapshotExpiryPolicy = 30 * 1000) {}\n\n async get(entry: ICacheEntry): Promise<any> {\n const key = this.keyFromEntry(entry);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return this.cache.get(key);\n }\n\n async put(entry: ICacheEntry, value: any) {\n const key = this.keyFromEntry(entry);\n this.cache.set(key, value);\n\n // Do not keep items too long in memory\n this.gc.cancel(key);\n this.gc.schedule(key, this.snapshotExpiryPolicy);\n }\n\n async removeEntries(file: IFileEntry): Promise<void> {\n Array.from(this.cache)\n .filter(([cachekey]) => {\n const docIdFromKey = cachekey.split(\"_\");\n if (docIdFromKey[0] === file.docId) {\n return true;\n }\n })\n .map(([cachekey]) => {\n this.cache.delete(cachekey);\n });\n }\n\n private keyFromEntry(entry: ICacheEntry): string {\n return `${entry.file.docId}_${entry.type}_${entry.key}`;\n }\n}\n\nexport class PromiseCacheWithOneHourSlidingExpiry<T> extends PromiseCache<string, T> {\n constructor(removeOnError?: (e: any) => boolean) {\n super({ expiry: { policy: \"sliding\", durationMs: 3600000 }, removeOnError });\n }\n}\n\n/**\n * Internal cache interface used within driver only\n */\nexport interface INonPersistentCache {\n /**\n * Cache of joined/joining session info\n */\n readonly sessionJoinCache: PromiseCache<string, {entryTime: number, joinSessionResponse: ISocketStorageDiscovery}>;\n\n /**\n * Cache of resolved/resolving file URLs\n */\n readonly fileUrlCache: PromiseCache<string, IOdspResolvedUrl>;\n}\n\n/**\n * Internal cache interface used within driver only\n */\nexport interface IOdspCache extends INonPersistentCache {\n /**\n * Persisted cache - only serializable content is allowed\n */\n readonly persistedCache: IPersistedFileCache;\n}\n\nexport class NonPersistentCache implements INonPersistentCache {\n public readonly sessionJoinCache =\n new PromiseCache<string, {entryTime: number, joinSessionResponse: ISocketStorageDiscovery}>();\n\n public readonly fileUrlCache = new PromiseCache<string, IOdspResolvedUrl>();\n}\n"]}
1
+ {"version":3,"file":"odspCache.js","sourceRoot":"","sources":["../src/odspCache.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 */\nimport { PromiseCache } from \"@fluidframework/common-utils\";\nimport {\n IOdspResolvedUrl,\n IFileEntry,\n IEntry,\n IPersistedCache,\n ICacheEntry,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISocketStorageDiscovery } from \"./contracts\";\n/**\n * Similar to IPersistedCache, but exposes cache interface for single file\n */\nexport interface IPersistedFileCache {\n get(entry: IEntry): Promise<any>;\n put(entry: IEntry, value: any): Promise<void>;\n removeEntries(): Promise<void>;\n}\n\n/**\n * Default local-only implementation of IPersistedCache,\n * used if no persisted cache is provided by the host\n */\nexport class LocalPersistentCache implements IPersistedCache {\n private readonly cache = new Map<string, any>();\n // For every document id there will be a single expiration entry inspite of the number of cache entries.\n private readonly docIdExpirationMap = new Map<string, ReturnType<typeof setTimeout>>();\n\n public constructor(private readonly snapshotExpiryPolicy = 3600 * 1000) { }\n\n async get(entry: ICacheEntry): Promise<any> {\n const key = this.keyFromEntry(entry);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return this.cache.get(key);\n }\n\n async put(entry: ICacheEntry, value: any) {\n const key = this.keyFromEntry(entry);\n this.cache.set(key, value);\n this.updateExpirationEntry(entry.file.docId);\n }\n\n async removeEntries(file: IFileEntry): Promise<void> {\n this.removeDocIdEntriesFromCache(file.docId);\n }\n\n private removeDocIdEntriesFromCache(docId: string) {\n this.removeExpirationEntry(docId);\n return Array.from(this.cache)\n .filter(([cachekey]) => {\n const docIdFromKey = cachekey.split(\"_\");\n if (docIdFromKey[0] === docId) {\n return true;\n }\n })\n .map(([cachekey]) => {\n this.cache.delete(cachekey);\n });\n }\n\n private removeExpirationEntry(docId: string) {\n const timeout = this.docIdExpirationMap.get(docId);\n if (timeout !== undefined) {\n clearTimeout(timeout);\n this.docIdExpirationMap.delete(docId);\n }\n }\n\n private updateExpirationEntry(docId: string) {\n this.removeExpirationEntry(docId);\n this.docIdExpirationMap.set(\n docId,\n setTimeout(\n () => {\n this.removeDocIdEntriesFromCache(docId);\n },\n this.snapshotExpiryPolicy,\n ),\n );\n }\n\n private keyFromEntry(entry: ICacheEntry): string {\n return `${entry.file.docId}_${entry.type}_${entry.key}`;\n }\n}\nexport class PromiseCacheWithOneHourSlidingExpiry<T> extends PromiseCache<string, T> {\n constructor(removeOnError?: (e: any) => boolean) {\n super({ expiry: { policy: \"sliding\", durationMs: 3600000 }, removeOnError });\n }\n}\n\n/**\n * Internal cache interface used within driver only\n */\nexport interface INonPersistentCache {\n /**\n * Cache of joined/joining session info\n */\n readonly sessionJoinCache: PromiseCache<string,\n { entryTime: number, joinSessionResponse: ISocketStorageDiscovery }>;\n\n /**\n * Cache of resolved/resolving file URLs\n */\n readonly fileUrlCache: PromiseCache<string, IOdspResolvedUrl>;\n}\n\n/**\n * Internal cache interface used within driver only\n */\nexport interface IOdspCache extends INonPersistentCache {\n /**\n * Persisted cache - only serializable content is allowed\n */\n readonly persistedCache: IPersistedFileCache;\n}\n\nexport class NonPersistentCache implements INonPersistentCache {\n public readonly sessionJoinCache =\n new PromiseCache<string, { entryTime: number, joinSessionResponse: ISocketStorageDiscovery }>();\n\n public readonly fileUrlCache = new PromiseCache<string, IOdspResolvedUrl>();\n}\n"]}
@@ -2,13 +2,13 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- /// <reference types="@types/socket.io-client" />
6
5
  import { ITelemetryLogger, IEvent } from "@fluidframework/common-definitions";
7
6
  import { DocumentDeltaConnection } from "@fluidframework/driver-base";
8
7
  import { OdspError } from "@fluidframework/odsp-driver-definitions";
9
8
  import { IAnyDriverError } from "@fluidframework/driver-utils";
10
9
  import { IFluidErrorBase } from "@fluidframework/telemetry-utils";
11
10
  import { IClient, IConnect } from "@fluidframework/protocol-definitions";
11
+ import type { io as SocketIOClientStatic } from "socket.io-client";
12
12
  import { EpochTracker } from "./epochTracker";
13
13
  export interface FlushResult {
14
14
  lastPersistedSequenceNumber?: number;
@@ -38,7 +38,7 @@ export declare class OdspDocumentDeltaConnection extends DocumentDeltaConnection
38
38
  * @param epochTracker - track epoch changes
39
39
  * @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache
40
40
  */
41
- static create(tenantId: string, documentId: string, token: string | null, io: SocketIOClientStatic, client: IClient, url: string, telemetryLogger: ITelemetryLogger, timeoutMs: number, epochTracker: EpochTracker, socketReferenceKeyPrefix: string | undefined): Promise<OdspDocumentDeltaConnection>;
41
+ static create(tenantId: string, documentId: string, token: string | null, io: typeof SocketIOClientStatic, client: IClient, url: string, telemetryLogger: ITelemetryLogger, timeoutMs: number, epochTracker: EpochTracker, socketReferenceKeyPrefix: string | undefined): Promise<OdspDocumentDeltaConnection>;
42
42
  private socketReference;
43
43
  private readonly requestOpsNoncePrefix;
44
44
  private pushCallCounter;
@@ -1 +1 @@
1
- {"version":3,"file":"odspDocumentDeltaConnection.d.ts","sourceRoot":"","sources":["../src/odspDocumentDeltaConnection.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAE9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAA6B,MAAM,iCAAiC,CAAC;AAC7F,OAAO,EACH,OAAO,EACP,QAAQ,EAIX,MAAM,sCAAsC,CAAC;AAG9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAQ9C,MAAM,WAAW,WAAW;IACxB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAMD,MAAM,WAAW,aAAc,SAAQ,MAAM;IACzC,CAAC,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,GAAG,SAAS,KAAK,IAAI,OAAE;CACxF;AAyID;;GAEG;AACH,qBAAa,2BAA4B,SAAQ,uBAAuB;IAoKhE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IAnKxC;;;;;;;;;;;;;;;OAeG;WACiB,MAAM,CACtB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,EAAE,EAAE,oBAAoB,EACxB,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,gBAAgB,EACjC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,YAAY,EAC1B,wBAAwB,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,2BAA2B,CAAC;IAsEvF,OAAO,CAAC,eAAe,CAA8B;IAErD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuE;IACjG,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,aAAa,CAAoC;IAEzD;;OAEG;IACH,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,QAAQ,UAAO,GAAG,eAAe;IAW3F;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,4BAA4B;IA8B3C;;;;;;OAMG;IACH,OAAO;IAYP;;;;;OAKG;IACK,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAwD9B,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC;IA4B1C,SAAS,CAAC,uBAAuB,UAAW,eAAe,GAAG,SAAS,UAErE;cAEc,UAAU,CAAC,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM;IAqFpE,SAAS,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI;IAsC9E;;OAEG;IACH,SAAS,CAAC,UAAU,CAAC,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe;CAe7E"}
1
+ {"version":3,"file":"odspDocumentDeltaConnection.d.ts","sourceRoot":"","sources":["../src/odspDocumentDeltaConnection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAE9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAA6B,MAAM,iCAAiC,CAAC;AAC7F,OAAO,EACH,OAAO,EACP,QAAQ,EAIX,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAU,EAAE,IAAI,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAG3E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAQ9C,MAAM,WAAW,WAAW;IACxB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAMD,MAAM,WAAW,aAAc,SAAQ,MAAM;IACzC,CAAC,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,GAAG,SAAS,KAAK,IAAI,OAAE;CACxF;AAyID;;GAEG;AACH,qBAAa,2BAA4B,SAAQ,uBAAuB;IAoKhE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IAnKxC;;;;;;;;;;;;;;;OAeG;WACiB,MAAM,CACtB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,EAAE,EAAE,OAAO,oBAAoB,EAC/B,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,gBAAgB,EACjC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,YAAY,EAC1B,wBAAwB,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,2BAA2B,CAAC;IAsEvF,OAAO,CAAC,eAAe,CAA8B;IAErD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuE;IACjG,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,aAAa,CAAoC;IAEzD;;OAEG;IACH,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,QAAQ,UAAO,GAAG,eAAe;IAW3F;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,4BAA4B;IA8B3C;;;;;;OAMG;IACH,OAAO;IAYP;;;;;OAKG;IACK,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAwD9B,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC;IA4B1C,SAAS,CAAC,uBAAuB,UAAW,eAAe,GAAG,SAAS,UAErE;cAEc,UAAU,CAAC,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM;IAqFpE,SAAS,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI;IAsC9E;;OAEG;IACH,SAAS,CAAC,UAAU,CAAC,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe;CAe7E"}
@@ -1 +1 @@
1
- {"version":3,"file":"odspDocumentDeltaConnection.js","sourceRoot":"","sources":["../src/odspDocumentDeltaConnection.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, IEvent } from \"@fluidframework/common-definitions\";\nimport { assert, performance, Deferred, TypedEventEmitter } from \"@fluidframework/common-utils\";\nimport { DocumentDeltaConnection } from \"@fluidframework/driver-base\";\nimport { OdspError } from \"@fluidframework/odsp-driver-definitions\";\nimport { IAnyDriverError } from \"@fluidframework/driver-utils\";\nimport { IFluidErrorBase, loggerToMonitoringContext } from \"@fluidframework/telemetry-utils\";\nimport {\n IClient,\n IConnect,\n INack,\n ISequencedDocumentMessage,\n ISignalMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport { v4 as uuid } from \"uuid\";\nimport { IOdspSocketError, IGetOpsResponse, IFlushOpsResponse } from \"./contracts\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { errorObjectFromSocketError } from \"./odspError\";\nimport { pkgVersion } from \"./packageVersion\";\n\nconst protocolVersions = [\"^0.4.0\", \"^0.3.0\", \"^0.2.0\", \"^0.1.0\"];\nconst feature_get_ops = \"api_get_ops\";\nconst feature_flush_ops = \"api_flush_ops\";\n\nexport interface FlushResult {\n lastPersistedSequenceNumber?: number;\n retryAfter?: number;\n}\n\n// How long to wait before disconnecting the socket after the last reference is removed\n// This allows reconnection after receiving a nack to be smooth\nconst socketReferenceBufferTime = 2000;\n\nexport interface ISocketEvents extends IEvent {\n (event: \"server_disconnect\", listener: (error: IFluidErrorBase & OdspError) => void);\n}\n\nclass SocketReference extends TypedEventEmitter<ISocketEvents> {\n private references: number = 1;\n private delayDeleteTimeout: ReturnType<typeof setTimeout> | undefined;\n private _socket: SocketIOClient.Socket | undefined;\n\n // When making decisions about socket reuse, we do not reuse disconnected socket.\n // But we want to differentiate the following case from disconnected case:\n // Socket that never connected and never failed, it's in \"attempting to connect\" mode\n // such sockets should be reused, despite socket.disconnected === true\n private isPendingInitialConnection = true;\n\n // Map of all existing socket io sockets. [url, tenantId, documentId] -> socket\n private static readonly socketIoSockets: Map<string, SocketReference> = new Map();\n\n public static find(key: string, logger: ITelemetryLogger) {\n const socketReference = SocketReference.socketIoSockets.get(key);\n\n // Verify the socket is healthy before reusing it\n if (socketReference && socketReference.disconnected) {\n // The socket is in a bad state. fully remove the reference\n socketReference.closeSocket();\n return undefined;\n }\n\n if (socketReference) {\n // Clear the pending deletion if there is one\n socketReference.clearTimer();\n socketReference.references++;\n }\n\n return socketReference;\n }\n\n /**\n * Removes a reference for the given key\n * Once the ref count hits 0, the socket is disconnected and removed\n * @param key - socket reference key\n * @param isFatalError - true if the socket reference should be removed immediately due to a fatal error\n */\n public removeSocketIoReference(isFatalError: boolean) {\n assert(this.references > 0, 0x09f /* \"No more socketIO refs to remove!\" */);\n this.references--;\n\n // see comment in disconnected() getter\n this.isPendingInitialConnection = false;\n\n if (isFatalError || this.disconnected) {\n this.closeSocket();\n return;\n }\n\n if (this.references === 0 && this.delayDeleteTimeout === undefined) {\n this.delayDeleteTimeout = setTimeout(() => {\n // We should not get here with active users.\n assert(this.references === 0, 0x0a0 /* \"Unexpected socketIO references on timeout\" */);\n this.closeSocket();\n }, socketReferenceBufferTime);\n }\n }\n\n public get socket() {\n if (!this._socket) {\n throw new Error(`Invalid socket for key \"${this.key}`);\n }\n return this._socket;\n }\n\n public constructor(public readonly key: string, socket: SocketIOClient.Socket) {\n super();\n\n this._socket = socket;\n assert(!SocketReference.socketIoSockets.has(key), 0x220 /* \"socket key collision\" */);\n SocketReference.socketIoSockets.set(key, this);\n\n // The server always closes the socket after sending this message\n // fully remove the socket reference now\n socket.on(\"server_disconnect\", (socketError: IOdspSocketError) => {\n // Treat all errors as recoverable, and rely on joinSession / reconnection flow to\n // filter out retryable vs. non-retryable cases.\n const error = errorObjectFromSocketError(socketError, \"server_disconnect\");\n error.canRetry = true;\n\n // see comment in disconnected() getter\n // Setting it here to ensure socket reuse does not happen if new request to connect\n // comes in from \"disconnect\" listener below, before we close socket.\n this.isPendingInitialConnection = false;\n\n // Explicitly cast error to the specified event args type to ensure type compatibility\n this.emit(\"server_disconnect\", error as IFluidErrorBase & OdspError);\n this.closeSocket();\n });\n }\n\n private clearTimer() {\n if (this.delayDeleteTimeout !== undefined) {\n clearTimeout(this.delayDeleteTimeout);\n this.delayDeleteTimeout = undefined;\n }\n }\n\n private closeSocket() {\n if (!this._socket) { return; }\n\n this.clearTimer();\n\n assert(SocketReference.socketIoSockets.get(this.key) === this,\n 0x0a1 /* \"Socket reference set unexpectedly does not point to this socket!\" */);\n SocketReference.socketIoSockets.delete(this.key);\n\n const socket = this._socket;\n this._socket = undefined;\n\n // Delay closing socket, to make sure all users of socket observe the same event that causes\n // this instance to close, and thus properly record reason for closure.\n // All event raising is synchronous, so clients will have a chance to react before socket is\n // closed without any extra data on why it was closed.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n Promise.resolve().then(() => { socket.disconnect(); });\n }\n\n private get disconnected() {\n if (this._socket === undefined) { return true; }\n if (this.socket.connected) { return false; }\n\n // We have a socket that is not connected. Possible cases:\n // 1) It was connected some time ago and lost connection. We do not want to reuse it.\n // 2) It failed to connect (was never connected).\n // 3) It was just created and never had a chance to connect - connection is in process.\n // We have to differentiate 1 from 2-3 (specifically 1 & 3) in order to be able to reuse socket in #3.\n // We will use the fact that socket had some activity. I.e. if socket disconnected, or client stopped using\n // socket, then removeSocketIoReference() will be called for it, and it will be the indiction that it's not #3.\n return !this.isPendingInitialConnection;\n }\n}\n\n/**\n * Represents a connection to a stream of delta updates\n */\nexport class OdspDocumentDeltaConnection extends DocumentDeltaConnection {\n /**\n * Create a OdspDocumentDeltaConnection\n * If url #1 fails to connect, will try url #2 if applicable.\n *\n * @param tenantId - the ID of the tenant\n * @param documentId - document ID\n * @param token - authorization token for storage service\n * @param io - websocket library\n * @param client - information about the client\n * @param mode - mode of the client\n * @param url - websocket URL\n * @param telemetryLogger - optional telemetry logger\n * @param timeoutMs - time limit on making the connection\n * @param epochTracker - track epoch changes\n * @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache\n */\n public static async create(\n tenantId: string,\n documentId: string,\n token: string | null,\n io: SocketIOClientStatic,\n client: IClient,\n url: string,\n telemetryLogger: ITelemetryLogger,\n timeoutMs: number,\n epochTracker: EpochTracker,\n socketReferenceKeyPrefix: string | undefined): Promise<OdspDocumentDeltaConnection> {\n const mc = loggerToMonitoringContext(telemetryLogger);\n\n // enable multiplexing when the websocket url does not include the tenant/document id\n const parsedUrl = new URL(url);\n const enableMultiplexing = !parsedUrl.searchParams.has(\"documentId\") && !parsedUrl.searchParams.has(\"tenantId\");\n\n // do not include the specific tenant/doc id in the ref key when multiplexing\n // this will allow multiple documents to share the same websocket connection\n const key = socketReferenceKeyPrefix ? `${socketReferenceKeyPrefix},${url}` : url;\n const socketReferenceKey = enableMultiplexing ? key : `${key},${tenantId},${documentId}`;\n\n const socketReference = OdspDocumentDeltaConnection.getOrCreateSocketIoReference(\n io, timeoutMs, socketReferenceKey, url, enableMultiplexing, tenantId, documentId, telemetryLogger);\n\n const socket = socketReference.socket;\n\n const connectMessage: IConnect = {\n client,\n id: documentId,\n mode: client.mode,\n tenantId,\n token, // Token is going to indicate tenant level information, etc...\n versions: protocolVersions,\n nonce: uuid(),\n epoch: epochTracker.fluidEpoch,\n relayUserAgent: [client.details.environment, ` driverVersion:${pkgVersion}`].join(\";\"),\n };\n\n // Reference to this client supporting get_ops flow.\n connectMessage.supportedFeatures = { };\n if (mc.config.getBoolean(\"Fluid.Driver.Odsp.GetOpsEnabled\") !== false) {\n connectMessage.supportedFeatures[feature_get_ops] = true;\n }\n\n const deltaConnection = new OdspDocumentDeltaConnection(\n socket,\n documentId,\n socketReference,\n telemetryLogger,\n enableMultiplexing);\n\n try {\n await deltaConnection.initialize(connectMessage, timeoutMs);\n await epochTracker.validateEpochFromPush(deltaConnection.details);\n } catch (errorObject) {\n if (errorObject !== null && typeof errorObject === \"object\") {\n // We have to special-case error types here in terms of what is re-triable.\n // These errors have to re-retried, we just need new joinSession result to connect to right server:\n // 400: Invalid tenant or document id. The WebSocket is connected to a different document\n // Document is full (with retryAfter)\n // 404: Invalid document. The document \\\"local/w1-...\\\" does not exist\n // But this has to stay not-retriable:\n // 406: Unsupported client protocol. This path is the only gatekeeper, have to fail!\n // 409: Epoch Version Mismatch. Client epoch and server epoch does not match, so app needs\n // to be refreshed.\n // This one is fine either way\n // 401/403: Code will retry once with new token either way, then it becomes fatal - on this path\n // and on join Session path.\n // 501: (Fluid not enabled): this is fine either way, as joinSession is gatekeeper\n if (errorObject.statusCode === 400 || errorObject.statusCode === 404) {\n errorObject.canRetry = true;\n }\n }\n throw errorObject;\n }\n\n return deltaConnection;\n }\n\n private socketReference: SocketReference | undefined;\n\n private readonly requestOpsNoncePrefix: string;\n private pushCallCounter = 0;\n private readonly getOpsMap: Map<string, { start: number, from: number, to: number }> = new Map();\n private flushOpNonce: string | undefined;\n private flushDeferred: Deferred<FlushResult> | undefined;\n\n /**\n * Error raising for socket.io issues\n */\n protected createErrorObject(handler: string, error?: any, canRetry = true): IAnyDriverError {\n // Note: we suspect the incoming error object is either:\n // - a socketError: add it to the OdspError object for driver to be able to parse it and reason over it.\n // - anything else: let base class handle it\n if (canRetry && Number.isInteger(error?.code) && typeof error?.message === \"string\") {\n return errorObjectFromSocketError(error as IOdspSocketError, handler);\n } else {\n return super.createErrorObject(handler, error, canRetry);\n }\n }\n\n /**\n * Gets or create a socket io connection for the given key\n */\n private static getOrCreateSocketIoReference(\n io: SocketIOClientStatic,\n timeoutMs: number,\n key: string,\n url: string,\n enableMultiplexing: boolean,\n tenantId: string,\n documentId: string,\n logger: ITelemetryLogger,\n ): SocketReference {\n const existingSocketReference = SocketReference.find(key, logger);\n if (existingSocketReference) {\n return existingSocketReference;\n }\n\n const query = enableMultiplexing ? undefined : { documentId, tenantId };\n\n const socket = io(\n url,\n {\n multiplex: false, // Don't rely on socket.io built-in multiplexing\n query,\n reconnection: false,\n transports: [\"websocket\"],\n timeout: timeoutMs,\n });\n\n return new SocketReference(key, socket);\n }\n\n /**\n * @param socket - websocket to be used\n * @param documentId - ID of the document\n * @param details - details of the websocket connection\n * @param socketReferenceKey - socket reference key\n * @param enableMultiplexing - If the websocket is multiplexing multiple documents\n */\n private constructor(\n socket: SocketIOClient.Socket,\n documentId: string,\n socketReference: SocketReference,\n logger: ITelemetryLogger,\n private readonly enableMultiplexing?: boolean,\n ) {\n super(socket, documentId, logger);\n this.socketReference = socketReference;\n this.requestOpsNoncePrefix = `${uuid()}-`;\n }\n\n /**\n * Retrieves ops from PUSH\n * @param from - inclusive\n * @param to - exclusive\n * @returns ops retrieved\n */\n public requestOps(from: number, to: number) {\n // Given that to is exclusive, we should be asking for at least something!\n assert(to > from, 0x272 /* \"empty request\" */);\n\n // PUSH may disable this functionality\n // back-compat: remove cast to any once latest version of IConnected is consumed\n if ((this.details as any).supportedFeatures?.[feature_get_ops] !== true) {\n return;\n }\n\n this.pushCallCounter++;\n const nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;\n const start = performance.now();\n\n // We may keep keep accumulating memory for nothing, if we are not getting responses.\n // Note that we should not have overlapping requests, as DeltaManager allows only one\n // outstanding request to storage, and that's the only way to get here.\n // But requests could be cancelled, and thus overlapping requests might be in the picture\n // If it happens, we do not care about stale requests.\n // So track some number of requests, but log if we get too many in flight - that likely\n // indicates an error somewhere.\n if (this.getOpsMap.size >= 5) {\n let time = start;\n let key: string | undefined;\n for (const [keyCandidate, value] of this.getOpsMap.entries()) {\n if (value.start <= time || key === undefined) {\n time = value.start;\n key = keyCandidate;\n }\n }\n const payloadToDelete = this.getOpsMap.get(key!)!;\n this.logger.sendErrorEvent({\n eventName: \"GetOpsTooMany\",\n nonce,\n from: payloadToDelete.from,\n to: payloadToDelete.to,\n length: payloadToDelete.to - payloadToDelete.from,\n duration: performance.now() - payloadToDelete.start,\n });\n this.getOpsMap.delete(key!);\n }\n this.getOpsMap.set(\n nonce,\n {\n start,\n from,\n to,\n },\n );\n this.socket.emit(\"get_ops\", this.clientId, {\n nonce,\n from,\n to: to - 1,\n });\n }\n\n public async flush(): Promise<FlushResult> {\n // back-compat: remove cast to any once latest version of IConnected is consumed\n if ((this.details as any).supportedFeatures?.[feature_flush_ops] !== true) {\n // Once single-commit summary is enabled end-to-end, flush support is a must!\n // The only alternative is change in design where SPO fetches ops from PUSH OR\n // summary includes required ops and SPO has some validation mechanism to ensure\n // they are not forged by client.\n // If design changes, we can reconsider it, but right now it's non-recoverable failure.\n this.logger.sendErrorEvent({ eventName: \"FlushOpsNotSupported\" });\n throw new Error(\"flush() API is not supported by PUSH, required for single-commit summaries\");\n }\n\n this.pushCallCounter++;\n const nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;\n // There should be only one flush ops in flight, kicked out by upload summary workflow\n // That said, it could timeout and request could be repeated, so theoretically we can\n // get overlapping requests, but it should be very rare\n if (this.flushDeferred !== undefined) {\n this.logger.sendErrorEvent({ eventName: \"FlushOpsTooMany\" });\n this.flushDeferred.reject(\"process involving flush() was cancelled OR unsupported concurrency\");\n }\n this.socket.emit(\"flush_ops\", this.clientId, { nonce });\n\n this.flushOpNonce = nonce;\n this.flushDeferred = new Deferred<FlushResult>();\n return this.flushDeferred.promise;\n }\n\n protected serverDisconnectHandler = (error: IFluidErrorBase & OdspError) => {\n this.disposeCore(true, error);\n };\n\n protected async initialize(connectMessage: IConnect, timeout: number) {\n if (this.enableMultiplexing) {\n // multiplex compatible early handlers\n this.earlyOpHandler = (messageDocumentId: string, msgs: ISequencedDocumentMessage[]) => {\n if (this.documentId === messageDocumentId) {\n this.queuedMessages.push(...msgs);\n }\n };\n\n this.earlySignalHandler = (msg: ISignalMessage, messageDocumentId?: string) => {\n if (messageDocumentId === undefined || messageDocumentId === this.documentId) {\n this.queuedSignals.push(msg);\n }\n };\n }\n\n this.socketReference!.once(\"server_disconnect\", this.serverDisconnectHandler);\n\n this.socket.on(\"get_ops_response\", (result: IGetOpsResponse) => {\n const messages = result.messages;\n const data = this.getOpsMap.get(result.nonce);\n // Due to socket multiplexing, this client may not have asked for any data\n // If so, there it most likely does not need these ops (otherwise it already asked for them)\n // Also we may have deleted entry in this.getOpsMap due to too many requests and too slow response.\n // But not processing such result may push us into infinite loop of fast requests and dropping all responses\n if (data !== undefined || result.nonce.indexOf(this.requestOpsNoncePrefix) === 0) {\n this.getOpsMap.delete(result.nonce);\n const common = {\n eventName: \"GetOps\",\n // We need nonce only to pair with GetOpsTooMany events, i.e. when record was deleted\n nonce: data === undefined ? result.nonce : undefined,\n code: result.code,\n from: data?.from,\n to: data?.to,\n duration: data === undefined ? undefined : performance.now() - data.start,\n };\n if (messages !== undefined && messages.length > 0) {\n this.logger.sendPerformanceEvent({\n ...common,\n first: messages[0].sequenceNumber,\n last: messages[messages.length - 1].sequenceNumber,\n length: messages.length,\n });\n this.emit(\"op\", this.documentId, messages);\n } else {\n this.logger.sendPerformanceEvent({\n ...common,\n length: 0,\n });\n }\n }\n });\n\n this.socket.on(\"flush_ops_response\", (result: IFlushOpsResponse) => {\n if (this.flushOpNonce === result.nonce) {\n const seq = result.lastPersistedSequenceNumber;\n let category: \"generic\" | \"error\" = \"generic\";\n if (result.lastPersistedSequenceNumber === undefined || result.code !== 200) {\n switch (result.code) {\n case 409:\n case 429:\n category = \"error\";\n break;\n case 204:\n break;\n default:\n category = \"error\";\n break;\n }\n }\n this.logger.sendTelemetryEvent({\n eventName: \"FlushResult\",\n code: result.code,\n sequenceNumber: seq,\n category,\n });\n this.flushDeferred!.resolve(result);\n this.flushDeferred = undefined;\n this.flushOpNonce = undefined;\n }\n });\n\n await super.initialize(connectMessage, timeout);\n }\n\n protected addTrackedListener(event: string, listener: (...args: any[]) => void) {\n // override some event listeners in order to support multiple documents/clients over the same websocket\n switch (event) {\n case \"op\":\n // per document op handling\n super.addTrackedListener(event, (documentId: string, msgs: ISequencedDocumentMessage[]) => {\n if (!this.enableMultiplexing || this.documentId === documentId) {\n listener(documentId, msgs);\n }\n });\n break;\n\n case \"signal\":\n // per document signal handling\n super.addTrackedListener(event, (msg: ISignalMessage, documentId?: string) => {\n if (!this.enableMultiplexing || !documentId || documentId === this.documentId) {\n listener(msg, documentId);\n }\n });\n break;\n\n case \"nack\":\n // per client / document nack handling\n super.addTrackedListener(event, (clientIdOrDocumentId: string, message: INack[]) => {\n if (clientIdOrDocumentId.length === 0 ||\n clientIdOrDocumentId === this.documentId ||\n (this.hasDetails && clientIdOrDocumentId === this.clientId)) {\n this.emit(\"nack\", clientIdOrDocumentId, message);\n }\n });\n break;\n\n default:\n super.addTrackedListener(event, listener);\n break;\n }\n }\n\n /**\n * Disconnect from the websocket\n */\n protected disconnect(socketProtocolError: boolean, reason: IAnyDriverError) {\n const socket = this.socketReference;\n assert(socket !== undefined, 0x0a2 /* \"reentrancy not supported!\" */);\n this.socketReference = undefined;\n\n this.socket.off(\"server_disconnect\", this.serverDisconnectHandler);\n\n if (!socketProtocolError && this.hasDetails) {\n // tell the server we are disconnecting this client from the document\n this.socket.emit(\"disconnect_document\", this.clientId, this.documentId);\n }\n\n socket.removeSocketIoReference(socketProtocolError);\n this.emit(\"disconnect\", reason);\n }\n}\n"]}
1
+ {"version":3,"file":"odspDocumentDeltaConnection.js","sourceRoot":"","sources":["../src/odspDocumentDeltaConnection.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, IEvent } from \"@fluidframework/common-definitions\";\nimport { assert, performance, Deferred, TypedEventEmitter } from \"@fluidframework/common-utils\";\nimport { DocumentDeltaConnection } from \"@fluidframework/driver-base\";\nimport { OdspError } from \"@fluidframework/odsp-driver-definitions\";\nimport { IAnyDriverError } from \"@fluidframework/driver-utils\";\nimport { IFluidErrorBase, loggerToMonitoringContext } from \"@fluidframework/telemetry-utils\";\nimport {\n IClient,\n IConnect,\n INack,\n ISequencedDocumentMessage,\n ISignalMessage,\n} from \"@fluidframework/protocol-definitions\";\nimport type { Socket, io as SocketIOClientStatic } from \"socket.io-client\";\nimport { v4 as uuid } from \"uuid\";\nimport { IOdspSocketError, IGetOpsResponse, IFlushOpsResponse } from \"./contracts\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { errorObjectFromSocketError } from \"./odspError\";\nimport { pkgVersion } from \"./packageVersion\";\n\nconst protocolVersions = [\"^0.4.0\", \"^0.3.0\", \"^0.2.0\", \"^0.1.0\"];\nconst feature_get_ops = \"api_get_ops\";\nconst feature_flush_ops = \"api_flush_ops\";\n\nexport interface FlushResult {\n lastPersistedSequenceNumber?: number;\n retryAfter?: number;\n}\n\n// How long to wait before disconnecting the socket after the last reference is removed\n// This allows reconnection after receiving a nack to be smooth\nconst socketReferenceBufferTime = 2000;\n\nexport interface ISocketEvents extends IEvent {\n (event: \"server_disconnect\", listener: (error: IFluidErrorBase & OdspError) => void);\n}\n\nclass SocketReference extends TypedEventEmitter<ISocketEvents> {\n private references: number = 1;\n private delayDeleteTimeout: ReturnType<typeof setTimeout> | undefined;\n private _socket: Socket | undefined;\n\n // When making decisions about socket reuse, we do not reuse disconnected socket.\n // But we want to differentiate the following case from disconnected case:\n // Socket that never connected and never failed, it's in \"attempting to connect\" mode\n // such sockets should be reused, despite socket.disconnected === true\n private isPendingInitialConnection = true;\n\n // Map of all existing socket io sockets. [url, tenantId, documentId] -> socket\n private static readonly socketIoSockets: Map<string, SocketReference> = new Map();\n\n public static find(key: string, logger: ITelemetryLogger) {\n const socketReference = SocketReference.socketIoSockets.get(key);\n\n // Verify the socket is healthy before reusing it\n if (socketReference && socketReference.disconnected) {\n // The socket is in a bad state. fully remove the reference\n socketReference.closeSocket();\n return undefined;\n }\n\n if (socketReference) {\n // Clear the pending deletion if there is one\n socketReference.clearTimer();\n socketReference.references++;\n }\n\n return socketReference;\n }\n\n /**\n * Removes a reference for the given key\n * Once the ref count hits 0, the socket is disconnected and removed\n * @param key - socket reference key\n * @param isFatalError - true if the socket reference should be removed immediately due to a fatal error\n */\n public removeSocketIoReference(isFatalError: boolean) {\n assert(this.references > 0, 0x09f /* \"No more socketIO refs to remove!\" */);\n this.references--;\n\n // see comment in disconnected() getter\n this.isPendingInitialConnection = false;\n\n if (isFatalError || this.disconnected) {\n this.closeSocket();\n return;\n }\n\n if (this.references === 0 && this.delayDeleteTimeout === undefined) {\n this.delayDeleteTimeout = setTimeout(() => {\n // We should not get here with active users.\n assert(this.references === 0, 0x0a0 /* \"Unexpected socketIO references on timeout\" */);\n this.closeSocket();\n }, socketReferenceBufferTime);\n }\n }\n\n public get socket() {\n if (!this._socket) {\n throw new Error(`Invalid socket for key \"${this.key}`);\n }\n return this._socket;\n }\n\n public constructor(public readonly key: string, socket: Socket) {\n super();\n\n this._socket = socket;\n assert(!SocketReference.socketIoSockets.has(key), 0x220 /* \"socket key collision\" */);\n SocketReference.socketIoSockets.set(key, this);\n\n // The server always closes the socket after sending this message\n // fully remove the socket reference now\n socket.on(\"server_disconnect\", (socketError: IOdspSocketError) => {\n // Treat all errors as recoverable, and rely on joinSession / reconnection flow to\n // filter out retryable vs. non-retryable cases.\n const error = errorObjectFromSocketError(socketError, \"server_disconnect\");\n error.canRetry = true;\n\n // see comment in disconnected() getter\n // Setting it here to ensure socket reuse does not happen if new request to connect\n // comes in from \"disconnect\" listener below, before we close socket.\n this.isPendingInitialConnection = false;\n\n // Explicitly cast error to the specified event args type to ensure type compatibility\n this.emit(\"server_disconnect\", error as IFluidErrorBase & OdspError);\n this.closeSocket();\n });\n }\n\n private clearTimer() {\n if (this.delayDeleteTimeout !== undefined) {\n clearTimeout(this.delayDeleteTimeout);\n this.delayDeleteTimeout = undefined;\n }\n }\n\n private closeSocket() {\n if (!this._socket) { return; }\n\n this.clearTimer();\n\n assert(SocketReference.socketIoSockets.get(this.key) === this,\n 0x0a1 /* \"Socket reference set unexpectedly does not point to this socket!\" */);\n SocketReference.socketIoSockets.delete(this.key);\n\n const socket = this._socket;\n this._socket = undefined;\n\n // Delay closing socket, to make sure all users of socket observe the same event that causes\n // this instance to close, and thus properly record reason for closure.\n // All event raising is synchronous, so clients will have a chance to react before socket is\n // closed without any extra data on why it was closed.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n Promise.resolve().then(() => { socket.disconnect(); });\n }\n\n private get disconnected() {\n if (this._socket === undefined) { return true; }\n if (this.socket.connected) { return false; }\n\n // We have a socket that is not connected. Possible cases:\n // 1) It was connected some time ago and lost connection. We do not want to reuse it.\n // 2) It failed to connect (was never connected).\n // 3) It was just created and never had a chance to connect - connection is in process.\n // We have to differentiate 1 from 2-3 (specifically 1 & 3) in order to be able to reuse socket in #3.\n // We will use the fact that socket had some activity. I.e. if socket disconnected, or client stopped using\n // socket, then removeSocketIoReference() will be called for it, and it will be the indiction that it's not #3.\n return !this.isPendingInitialConnection;\n }\n}\n\n/**\n * Represents a connection to a stream of delta updates\n */\nexport class OdspDocumentDeltaConnection extends DocumentDeltaConnection {\n /**\n * Create a OdspDocumentDeltaConnection\n * If url #1 fails to connect, will try url #2 if applicable.\n *\n * @param tenantId - the ID of the tenant\n * @param documentId - document ID\n * @param token - authorization token for storage service\n * @param io - websocket library\n * @param client - information about the client\n * @param mode - mode of the client\n * @param url - websocket URL\n * @param telemetryLogger - optional telemetry logger\n * @param timeoutMs - time limit on making the connection\n * @param epochTracker - track epoch changes\n * @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache\n */\n public static async create(\n tenantId: string,\n documentId: string,\n token: string | null,\n io: typeof SocketIOClientStatic,\n client: IClient,\n url: string,\n telemetryLogger: ITelemetryLogger,\n timeoutMs: number,\n epochTracker: EpochTracker,\n socketReferenceKeyPrefix: string | undefined): Promise<OdspDocumentDeltaConnection> {\n const mc = loggerToMonitoringContext(telemetryLogger);\n\n // enable multiplexing when the websocket url does not include the tenant/document id\n const parsedUrl = new URL(url);\n const enableMultiplexing = !parsedUrl.searchParams.has(\"documentId\") && !parsedUrl.searchParams.has(\"tenantId\");\n\n // do not include the specific tenant/doc id in the ref key when multiplexing\n // this will allow multiple documents to share the same websocket connection\n const key = socketReferenceKeyPrefix ? `${socketReferenceKeyPrefix},${url}` : url;\n const socketReferenceKey = enableMultiplexing ? key : `${key},${tenantId},${documentId}`;\n\n const socketReference = OdspDocumentDeltaConnection.getOrCreateSocketIoReference(\n io, timeoutMs, socketReferenceKey, url, enableMultiplexing, tenantId, documentId, telemetryLogger);\n\n const socket = socketReference.socket;\n\n const connectMessage: IConnect = {\n client,\n id: documentId,\n mode: client.mode,\n tenantId,\n token, // Token is going to indicate tenant level information, etc...\n versions: protocolVersions,\n nonce: uuid(),\n epoch: epochTracker.fluidEpoch,\n relayUserAgent: [client.details.environment, ` driverVersion:${pkgVersion}`].join(\";\"),\n };\n\n // Reference to this client supporting get_ops flow.\n connectMessage.supportedFeatures = { };\n if (mc.config.getBoolean(\"Fluid.Driver.Odsp.GetOpsEnabled\") !== false) {\n connectMessage.supportedFeatures[feature_get_ops] = true;\n }\n\n const deltaConnection = new OdspDocumentDeltaConnection(\n socket,\n documentId,\n socketReference,\n telemetryLogger,\n enableMultiplexing);\n\n try {\n await deltaConnection.initialize(connectMessage, timeoutMs);\n await epochTracker.validateEpochFromPush(deltaConnection.details);\n } catch (errorObject) {\n if (errorObject !== null && typeof errorObject === \"object\") {\n // We have to special-case error types here in terms of what is re-triable.\n // These errors have to re-retried, we just need new joinSession result to connect to right server:\n // 400: Invalid tenant or document id. The WebSocket is connected to a different document\n // Document is full (with retryAfter)\n // 404: Invalid document. The document \\\"local/w1-...\\\" does not exist\n // But this has to stay not-retriable:\n // 406: Unsupported client protocol. This path is the only gatekeeper, have to fail!\n // 409: Epoch Version Mismatch. Client epoch and server epoch does not match, so app needs\n // to be refreshed.\n // This one is fine either way\n // 401/403: Code will retry once with new token either way, then it becomes fatal - on this path\n // and on join Session path.\n // 501: (Fluid not enabled): this is fine either way, as joinSession is gatekeeper\n if (errorObject.statusCode === 400 || errorObject.statusCode === 404) {\n errorObject.canRetry = true;\n }\n }\n throw errorObject;\n }\n\n return deltaConnection;\n }\n\n private socketReference: SocketReference | undefined;\n\n private readonly requestOpsNoncePrefix: string;\n private pushCallCounter = 0;\n private readonly getOpsMap: Map<string, { start: number, from: number, to: number }> = new Map();\n private flushOpNonce: string | undefined;\n private flushDeferred: Deferred<FlushResult> | undefined;\n\n /**\n * Error raising for socket.io issues\n */\n protected createErrorObject(handler: string, error?: any, canRetry = true): IAnyDriverError {\n // Note: we suspect the incoming error object is either:\n // - a socketError: add it to the OdspError object for driver to be able to parse it and reason over it.\n // - anything else: let base class handle it\n if (canRetry && Number.isInteger(error?.code) && typeof error?.message === \"string\") {\n return errorObjectFromSocketError(error as IOdspSocketError, handler);\n } else {\n return super.createErrorObject(handler, error, canRetry);\n }\n }\n\n /**\n * Gets or create a socket io connection for the given key\n */\n private static getOrCreateSocketIoReference(\n io: typeof SocketIOClientStatic,\n timeoutMs: number,\n key: string,\n url: string,\n enableMultiplexing: boolean,\n tenantId: string,\n documentId: string,\n logger: ITelemetryLogger,\n ): SocketReference {\n const existingSocketReference = SocketReference.find(key, logger);\n if (existingSocketReference) {\n return existingSocketReference;\n }\n\n const query = enableMultiplexing ? undefined : { documentId, tenantId };\n\n const socket = io(\n url,\n {\n multiplex: false, // Don't rely on socket.io built-in multiplexing\n query,\n reconnection: false,\n transports: [\"websocket\"],\n timeout: timeoutMs,\n });\n\n return new SocketReference(key, socket);\n }\n\n /**\n * @param socket - websocket to be used\n * @param documentId - ID of the document\n * @param details - details of the websocket connection\n * @param socketReferenceKey - socket reference key\n * @param enableMultiplexing - If the websocket is multiplexing multiple documents\n */\n private constructor(\n socket: Socket,\n documentId: string,\n socketReference: SocketReference,\n logger: ITelemetryLogger,\n private readonly enableMultiplexing?: boolean,\n ) {\n super(socket, documentId, logger);\n this.socketReference = socketReference;\n this.requestOpsNoncePrefix = `${uuid()}-`;\n }\n\n /**\n * Retrieves ops from PUSH\n * @param from - inclusive\n * @param to - exclusive\n * @returns ops retrieved\n */\n public requestOps(from: number, to: number) {\n // Given that to is exclusive, we should be asking for at least something!\n assert(to > from, 0x272 /* \"empty request\" */);\n\n // PUSH may disable this functionality\n // back-compat: remove cast to any once latest version of IConnected is consumed\n if ((this.details as any).supportedFeatures?.[feature_get_ops] !== true) {\n return;\n }\n\n this.pushCallCounter++;\n const nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;\n const start = performance.now();\n\n // We may keep keep accumulating memory for nothing, if we are not getting responses.\n // Note that we should not have overlapping requests, as DeltaManager allows only one\n // outstanding request to storage, and that's the only way to get here.\n // But requests could be cancelled, and thus overlapping requests might be in the picture\n // If it happens, we do not care about stale requests.\n // So track some number of requests, but log if we get too many in flight - that likely\n // indicates an error somewhere.\n if (this.getOpsMap.size >= 5) {\n let time = start;\n let key: string | undefined;\n for (const [keyCandidate, value] of this.getOpsMap.entries()) {\n if (value.start <= time || key === undefined) {\n time = value.start;\n key = keyCandidate;\n }\n }\n const payloadToDelete = this.getOpsMap.get(key!)!;\n this.logger.sendErrorEvent({\n eventName: \"GetOpsTooMany\",\n nonce,\n from: payloadToDelete.from,\n to: payloadToDelete.to,\n length: payloadToDelete.to - payloadToDelete.from,\n duration: performance.now() - payloadToDelete.start,\n });\n this.getOpsMap.delete(key!);\n }\n this.getOpsMap.set(\n nonce,\n {\n start,\n from,\n to,\n },\n );\n this.socket.emit(\"get_ops\", this.clientId, {\n nonce,\n from,\n to: to - 1,\n });\n }\n\n public async flush(): Promise<FlushResult> {\n // back-compat: remove cast to any once latest version of IConnected is consumed\n if ((this.details as any).supportedFeatures?.[feature_flush_ops] !== true) {\n // Once single-commit summary is enabled end-to-end, flush support is a must!\n // The only alternative is change in design where SPO fetches ops from PUSH OR\n // summary includes required ops and SPO has some validation mechanism to ensure\n // they are not forged by client.\n // If design changes, we can reconsider it, but right now it's non-recoverable failure.\n this.logger.sendErrorEvent({ eventName: \"FlushOpsNotSupported\" });\n throw new Error(\"flush() API is not supported by PUSH, required for single-commit summaries\");\n }\n\n this.pushCallCounter++;\n const nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;\n // There should be only one flush ops in flight, kicked out by upload summary workflow\n // That said, it could timeout and request could be repeated, so theoretically we can\n // get overlapping requests, but it should be very rare\n if (this.flushDeferred !== undefined) {\n this.logger.sendErrorEvent({ eventName: \"FlushOpsTooMany\" });\n this.flushDeferred.reject(\"process involving flush() was cancelled OR unsupported concurrency\");\n }\n this.socket.emit(\"flush_ops\", this.clientId, { nonce });\n\n this.flushOpNonce = nonce;\n this.flushDeferred = new Deferred<FlushResult>();\n return this.flushDeferred.promise;\n }\n\n protected serverDisconnectHandler = (error: IFluidErrorBase & OdspError) => {\n this.disposeCore(true, error);\n };\n\n protected async initialize(connectMessage: IConnect, timeout: number) {\n if (this.enableMultiplexing) {\n // multiplex compatible early handlers\n this.earlyOpHandler = (messageDocumentId: string, msgs: ISequencedDocumentMessage[]) => {\n if (this.documentId === messageDocumentId) {\n this.queuedMessages.push(...msgs);\n }\n };\n\n this.earlySignalHandler = (msg: ISignalMessage, messageDocumentId?: string) => {\n if (messageDocumentId === undefined || messageDocumentId === this.documentId) {\n this.queuedSignals.push(msg);\n }\n };\n }\n\n this.socketReference!.once(\"server_disconnect\", this.serverDisconnectHandler);\n\n this.socket.on(\"get_ops_response\", (result: IGetOpsResponse) => {\n const messages = result.messages;\n const data = this.getOpsMap.get(result.nonce);\n // Due to socket multiplexing, this client may not have asked for any data\n // If so, there it most likely does not need these ops (otherwise it already asked for them)\n // Also we may have deleted entry in this.getOpsMap due to too many requests and too slow response.\n // But not processing such result may push us into infinite loop of fast requests and dropping all responses\n if (data !== undefined || result.nonce.indexOf(this.requestOpsNoncePrefix) === 0) {\n this.getOpsMap.delete(result.nonce);\n const common = {\n eventName: \"GetOps\",\n // We need nonce only to pair with GetOpsTooMany events, i.e. when record was deleted\n nonce: data === undefined ? result.nonce : undefined,\n code: result.code,\n from: data?.from,\n to: data?.to,\n duration: data === undefined ? undefined : performance.now() - data.start,\n };\n if (messages !== undefined && messages.length > 0) {\n this.logger.sendPerformanceEvent({\n ...common,\n first: messages[0].sequenceNumber,\n last: messages[messages.length - 1].sequenceNumber,\n length: messages.length,\n });\n this.emit(\"op\", this.documentId, messages);\n } else {\n this.logger.sendPerformanceEvent({\n ...common,\n length: 0,\n });\n }\n }\n });\n\n this.socket.on(\"flush_ops_response\", (result: IFlushOpsResponse) => {\n if (this.flushOpNonce === result.nonce) {\n const seq = result.lastPersistedSequenceNumber;\n let category: \"generic\" | \"error\" = \"generic\";\n if (result.lastPersistedSequenceNumber === undefined || result.code !== 200) {\n switch (result.code) {\n case 409:\n case 429:\n category = \"error\";\n break;\n case 204:\n break;\n default:\n category = \"error\";\n break;\n }\n }\n this.logger.sendTelemetryEvent({\n eventName: \"FlushResult\",\n code: result.code,\n sequenceNumber: seq,\n category,\n });\n this.flushDeferred!.resolve(result);\n this.flushDeferred = undefined;\n this.flushOpNonce = undefined;\n }\n });\n\n await super.initialize(connectMessage, timeout);\n }\n\n protected addTrackedListener(event: string, listener: (...args: any[]) => void) {\n // override some event listeners in order to support multiple documents/clients over the same websocket\n switch (event) {\n case \"op\":\n // per document op handling\n super.addTrackedListener(event, (documentId: string, msgs: ISequencedDocumentMessage[]) => {\n if (!this.enableMultiplexing || this.documentId === documentId) {\n listener(documentId, msgs);\n }\n });\n break;\n\n case \"signal\":\n // per document signal handling\n super.addTrackedListener(event, (msg: ISignalMessage, documentId?: string) => {\n if (!this.enableMultiplexing || !documentId || documentId === this.documentId) {\n listener(msg, documentId);\n }\n });\n break;\n\n case \"nack\":\n // per client / document nack handling\n super.addTrackedListener(event, (clientIdOrDocumentId: string, message: INack[]) => {\n if (clientIdOrDocumentId.length === 0 ||\n clientIdOrDocumentId === this.documentId ||\n (this.hasDetails && clientIdOrDocumentId === this.clientId)) {\n this.emit(\"nack\", clientIdOrDocumentId, message);\n }\n });\n break;\n\n default:\n super.addTrackedListener(event, listener);\n break;\n }\n }\n\n /**\n * Disconnect from the websocket\n */\n protected disconnect(socketProtocolError: boolean, reason: IAnyDriverError) {\n const socket = this.socketReference;\n assert(socket !== undefined, 0x0a2 /* \"reentrancy not supported!\" */);\n this.socketReference = undefined;\n\n this.socket.off(\"server_disconnect\", this.serverDisconnectHandler);\n\n if (!socketProtocolError && this.hasDetails) {\n // tell the server we are disconnecting this client from the document\n this.socket.emit(\"disconnect_document\", this.clientId, this.documentId);\n }\n\n socket.removeSocketIoReference(socketProtocolError);\n this.emit(\"disconnect\", reason);\n }\n}\n"]}
@@ -2,11 +2,11 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- /// <reference types="@types/socket.io-client" />
6
5
  import { ITelemetryLogger } from "@fluidframework/common-definitions";
7
6
  import { IDocumentDeltaConnection, IDocumentDeltaStorageService, IDocumentService, IResolvedUrl, IDocumentStorageService, IDocumentServicePolicies } from "@fluidframework/driver-definitions";
8
7
  import { IClient, ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
9
8
  import { IOdspResolvedUrl, TokenFetchOptions, HostStoragePolicy, InstrumentedStorageTokenFetcher } from "@fluidframework/odsp-driver-definitions";
9
+ import type { io as SocketIOClientStatic } from "socket.io-client";
10
10
  import { IOdspCache } from "./odspCache";
11
11
  import { EpochTracker } from "./epochTracker";
12
12
  import { OpsCache } from "./opsCaching";
@@ -38,7 +38,7 @@ export declare class OdspDocumentService implements IDocumentService {
38
38
  * @param epochTracker - This helper class which adds epoch to backend calls made by returned service instance.
39
39
  * @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache
40
40
  */
41
- static create(resolvedUrl: IResolvedUrl, getStorageToken: InstrumentedStorageTokenFetcher, getWebsocketToken: ((options: TokenFetchOptions) => Promise<string | null>) | undefined, logger: ITelemetryLogger, socketIoClientFactory: () => Promise<SocketIOClientStatic>, cache: IOdspCache, hostPolicy: HostStoragePolicy, epochTracker: EpochTracker, socketReferenceKeyPrefix?: string): Promise<IDocumentService>;
41
+ static create(resolvedUrl: IResolvedUrl, getStorageToken: InstrumentedStorageTokenFetcher, getWebsocketToken: ((options: TokenFetchOptions) => Promise<string | null>) | undefined, logger: ITelemetryLogger, socketIoClientFactory: () => Promise<typeof SocketIOClientStatic>, cache: IOdspCache, hostPolicy: HostStoragePolicy, epochTracker: EpochTracker, socketReferenceKeyPrefix?: string): Promise<IDocumentService>;
42
42
  private storageManager?;
43
43
  private readonly mc;
44
44
  private readonly joinSessionKey;
@@ -74,6 +74,8 @@ export declare class OdspDocumentService implements IDocumentService {
74
74
  * @returns returns the document delta storage service for sharepoint driver.
75
75
  */
76
76
  connectToDeltaStorage(): Promise<IDocumentDeltaStorageService>;
77
+ /** Annotate the given error indicating which connection step failed */
78
+ private annotateConnectionError;
77
79
  /**
78
80
  * Connects to a delta stream endpoint for emitting ops.
79
81
  *
@@ -86,17 +88,16 @@ export declare class OdspDocumentService implements IDocumentService {
86
88
  private joinSessionCore;
87
89
  private calculateJoinSessionRefreshDelta;
88
90
  /**
89
- * Connects to a delta stream endpoint
90
- * If url #1 fails to connect, tries url #2 if applicable
91
+ * Creats a connection to the given delta stream endpoint
91
92
  *
92
93
  * @param tenantId - the ID of the tenant
93
94
  * @param documentId - document ID
94
- * @param token - authorization token for storage service
95
+ * @param token - authorization token for delta service
95
96
  * @param io - websocket library
96
97
  * @param client - information about the client
97
98
  * @param webSocketUrl - websocket URL
98
99
  */
99
- private connectToDeltaStreamWithRetry;
100
+ private createDeltaConnection;
100
101
  dispose(error?: any): void;
101
102
  protected get opsCache(): OpsCache | undefined;
102
103
  protected opsReceived(ops: ISequencedDocumentMessage[]): void;
@@ -1 +1 @@
1
- {"version":3,"file":"odspDocumentService.d.ts","sourceRoot":"","sources":["../src/odspDocumentService.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAOtE,OAAO,EACH,wBAAwB,EACxB,4BAA4B,EAC5B,gBAAgB,EAChB,YAAY,EACZ,uBAAuB,EACvB,wBAAwB,EAE3B,MAAM,oCAAoC,CAAC;AAG5C,OAAO,EACH,OAAO,EACP,yBAAyB,EAC5B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EAEjB,iBAAiB,EACjB,+BAA+B,EAElC,MAAM,yCAAyC,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAOzC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIxC;;;GAGG;AACH,qBAAa,mBAAoB,YAAW,gBAAgB;aAqEpC,eAAe,EAAE,gBAAgB;IACjD,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAElC,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK;IAEtB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC;IA5E9C,OAAO,CAAC,SAAS,CAA2B;IAE5C,OAAO,CAAC,uBAAuB,CAA4C;IAC3E;;;;;;;;;;;;;OAaG;WACiB,MAAM,CACtB,WAAW,EAAE,YAAY,EACzB,eAAe,EAAE,+BAA+B,EAChD,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,SAAS,EACvF,MAAM,EAAE,gBAAgB,EACxB,qBAAqB,EAAE,MAAM,OAAO,CAAC,oBAAoB,CAAC,EAC1D,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,iBAAiB,EAC7B,YAAY,EAAE,YAAY,EAC1B,wBAAwB,CAAC,EAAE,MAAM,GAClC,OAAO,CAAC,gBAAgB,CAAC;IAc5B,OAAO,CAAC,cAAc,CAAC,CAA6B;IAEpD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;IAEvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAExC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4B;IAEvD,OAAO,CAAC,SAAS,CAAC,CAAW;IAE7B,OAAO,CAAC,iBAAiB,CAAC,CAA8B;IAExD;;;;;;;;;;;;;OAaG;IACH,OAAO;IAkCP,IAAW,WAAW,IAAI,YAAY,CAErC;IACD,IAAW,QAAQ,6BAElB;IAED;;;;OAIG;IACU,gBAAgB,IAAI,OAAO,CAAC,uBAAuB,CAAC;IAuBjE;;;;OAIG;IACU,qBAAqB,IAAI,OAAO,CAAC,4BAA4B,CAAC;IA+B3E;;;;OAIG;IACU,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,wBAAwB,CAAC;IA0DrF,OAAO,CAAC,qBAAqB;YAOf,0BAA0B;YAa1B,WAAW;YA0BX,eAAe;IAuE7B,OAAO,CAAC,gCAAgC;IAKxC;;;;;;;;;;OAUG;YACW,6BAA6B;IAkCpC,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG;IAa1B,SAAS,KAAK,QAAQ,yBA8BrB;IAID,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,yBAAyB,EAAE;CAQzD"}
1
+ {"version":3,"file":"odspDocumentService.d.ts","sourceRoot":"","sources":["../src/odspDocumentService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAStE,OAAO,EACH,wBAAwB,EACxB,4BAA4B,EAC5B,gBAAgB,EAChB,YAAY,EACZ,uBAAuB,EACvB,wBAAwB,EAE3B,MAAM,oCAAoC,CAAC;AAG5C,OAAO,EACH,OAAO,EACP,yBAAyB,EAC5B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EAEjB,iBAAiB,EACjB,+BAA+B,EAElC,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAE,EAAE,IAAI,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAEnE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAOzC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIxC;;;GAGG;AACH,qBAAa,mBAAoB,YAAW,gBAAgB;aAqEpC,eAAe,EAAE,gBAAgB;IACjD,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAElC,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK;IAEtB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC;IA5E9C,OAAO,CAAC,SAAS,CAA2B;IAE5C,OAAO,CAAC,uBAAuB,CAA4C;IAC3E;;;;;;;;;;;;;OAaG;WACiB,MAAM,CACtB,WAAW,EAAE,YAAY,EACzB,eAAe,EAAE,+BAA+B,EAChD,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,SAAS,EACvF,MAAM,EAAE,gBAAgB,EACxB,qBAAqB,EAAE,MAAM,OAAO,CAAC,OAAO,oBAAoB,CAAC,EACjE,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,iBAAiB,EAC7B,YAAY,EAAE,YAAY,EAC1B,wBAAwB,CAAC,EAAE,MAAM,GAClC,OAAO,CAAC,gBAAgB,CAAC;IAc5B,OAAO,CAAC,cAAc,CAAC,CAA6B;IAEpD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;IAEvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAExC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4B;IAEvD,OAAO,CAAC,SAAS,CAAC,CAAW;IAE7B,OAAO,CAAC,iBAAiB,CAAC,CAA8B;IAExD;;;;;;;;;;;;;OAaG;IACH,OAAO;IAkCP,IAAW,WAAW,IAAI,YAAY,CAErC;IACD,IAAW,QAAQ,6BAElB;IAED;;;;OAIG;IACU,gBAAgB,IAAI,OAAO,CAAC,uBAAuB,CAAC;IAuBjE;;;;OAIG;IACU,qBAAqB,IAAI,OAAO,CAAC,4BAA4B,CAAC;IA+B3E,uEAAuE;IACvE,OAAO,CAAC,uBAAuB;IAW/B;;;;OAIG;IACU,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAuErF,OAAO,CAAC,qBAAqB;YAOf,0BAA0B;YAa1B,WAAW;YA0BX,eAAe;IAuE7B,OAAO,CAAC,gCAAgC;IAKxC;;;;;;;;;OASG;YACW,qBAAqB;IAkC5B,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG;IAa1B,SAAS,KAAK,QAAQ,yBA8BrB;IAID,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,yBAAyB,EAAE;CAQzD"}
@@ -127,6 +127,13 @@ class OdspDocumentService {
127
127
  }
128
128
  }, (ops) => this.opsReceived(ops));
129
129
  }
130
+ /** Annotate the given error indicating which connection step failed */
131
+ annotateConnectionError(error, failedConnectionStep, separateTokenRequest) {
132
+ return telemetry_utils_1.normalizeError(error, { props: {
133
+ failedConnectionStep,
134
+ separateTokenRequest,
135
+ } });
136
+ }
130
137
  /**
131
138
  * Connects to a delta stream endpoint for emitting ops.
132
139
  *
@@ -141,18 +148,21 @@ class OdspDocumentService {
141
148
  const websocketTokenPromise = requestWebsocketTokenFromJoinSession
142
149
  ? Promise.resolve(null)
143
150
  : this.getWebsocketToken(options);
151
+ const annotateAndRethrowConnectionError = (step) => (error) => {
152
+ throw this.annotateConnectionError(error, step, !requestWebsocketTokenFromJoinSession);
153
+ };
144
154
  const joinSessionPromise = this.joinSession(requestWebsocketTokenFromJoinSession, options);
145
155
  const [websocketEndpoint, websocketToken, io] = await Promise.all([
146
- joinSessionPromise,
147
- websocketTokenPromise,
148
- this.socketIoClientFactory(),
156
+ joinSessionPromise.catch(annotateAndRethrowConnectionError("joinSession")),
157
+ websocketTokenPromise.catch(annotateAndRethrowConnectionError("getWebsocketToken")),
158
+ this.socketIoClientFactory().catch(annotateAndRethrowConnectionError("socketIoClientFactory")),
149
159
  ]);
150
160
  const finalWebsocketToken = websocketToken !== null && websocketToken !== void 0 ? websocketToken : (websocketEndpoint.socketToken || null);
151
161
  if (finalWebsocketToken === null) {
152
- throw new driver_utils_1.NonRetryableError("Websocket token is null", odsp_driver_definitions_1.OdspErrorType.fetchTokenError, { driverVersion: packageVersion_1.pkgVersion });
162
+ throw this.annotateConnectionError(new driver_utils_1.NonRetryableError("Websocket token is null", odsp_driver_definitions_1.OdspErrorType.fetchTokenError, { driverVersion: packageVersion_1.pkgVersion }), "getWebsocketToken", !requestWebsocketTokenFromJoinSession);
153
163
  }
154
164
  try {
155
- const connection = await this.connectToDeltaStreamWithRetry(websocketEndpoint.tenantId, websocketEndpoint.id, finalWebsocketToken, io, client, websocketEndpoint.deltaStreamSocketUrl);
165
+ const connection = await this.createDeltaConnection(websocketEndpoint.tenantId, websocketEndpoint.id, finalWebsocketToken, io, client, websocketEndpoint.deltaStreamSocketUrl);
156
166
  connection.on("op", (documentId, ops) => {
157
167
  this.opsReceived(ops);
158
168
  });
@@ -171,10 +181,11 @@ class OdspDocumentService {
171
181
  }
172
182
  catch (error) {
173
183
  this.cache.sessionJoinCache.remove(this.joinSessionKey);
184
+ const normalizedError = this.annotateConnectionError(error, "createDeltaConnection", !requestWebsocketTokenFromJoinSession);
174
185
  if (typeof error === "object" && error !== null) {
175
- error.socketDocumentId = websocketEndpoint.id;
186
+ normalizedError.addTelemetryProperties({ socketDocumentId: websocketEndpoint.id });
176
187
  }
177
- throw error;
188
+ throw normalizedError;
178
189
  }
179
190
  });
180
191
  }
@@ -230,11 +241,11 @@ class OdspDocumentService {
230
241
  };
231
242
  const getResponseAndRefreshAfterDeltaMs = async () => {
232
243
  var _a;
233
- let response = await this.cache.sessionJoinCache.addOrGet(this.joinSessionKey, executeFetch);
244
+ let _response = await this.cache.sessionJoinCache.addOrGet(this.joinSessionKey, executeFetch);
234
245
  // If the response does not contain refreshSessionDurationSeconds, then treat it as old flow and let the
235
246
  // cache entry to be treated as expired after 1 hour.
236
- response.joinSessionResponse.refreshSessionDurationSeconds = (_a = response.joinSessionResponse.refreshSessionDurationSeconds) !== null && _a !== void 0 ? _a : 3600;
237
- return Object.assign(Object.assign({}, response), { refreshAfterDeltaMs: this.calculateJoinSessionRefreshDelta(response.entryTime, response.joinSessionResponse.refreshSessionDurationSeconds) });
247
+ _response.joinSessionResponse.refreshSessionDurationSeconds = (_a = _response.joinSessionResponse.refreshSessionDurationSeconds) !== null && _a !== void 0 ? _a : 3600;
248
+ return Object.assign(Object.assign({}, _response), { refreshAfterDeltaMs: this.calculateJoinSessionRefreshDelta(_response.entryTime, _response.joinSessionResponse.refreshSessionDurationSeconds) });
238
249
  };
239
250
  let response = await getResponseAndRefreshAfterDeltaMs();
240
251
  // This means that the cached entry has expired(This should not be possible if the response is fetched
@@ -254,7 +265,6 @@ class OdspDocumentService {
254
265
  .catch((error) => {
255
266
  this.mc.logger.sendErrorEvent(Object.assign({ eventName: "JoinSessionRefreshError" }, props), error);
256
267
  });
257
- ;
258
268
  }
259
269
  else {
260
270
  // Logging just for informational purposes to help with debugging as this is a new feature.
@@ -268,17 +278,16 @@ class OdspDocumentService {
268
278
  return responseFetchTime + ((refreshSessionDurationSeconds * 1000) - 30000) - Date.now();
269
279
  }
270
280
  /**
271
- * Connects to a delta stream endpoint
272
- * If url #1 fails to connect, tries url #2 if applicable
281
+ * Creats a connection to the given delta stream endpoint
273
282
  *
274
283
  * @param tenantId - the ID of the tenant
275
284
  * @param documentId - document ID
276
- * @param token - authorization token for storage service
285
+ * @param token - authorization token for delta service
277
286
  * @param io - websocket library
278
287
  * @param client - information about the client
279
288
  * @param webSocketUrl - websocket URL
280
289
  */
281
- async connectToDeltaStreamWithRetry(tenantId, documentId, token, io, client, webSocketUrl) {
290
+ async createDeltaConnection(tenantId, documentId, token, io, client, webSocketUrl) {
282
291
  const startTime = common_utils_1.performance.now();
283
292
  const connection = await odspDocumentDeltaConnection_1.OdspDocumentDeltaConnection.create(tenantId, documentId, token, io, client, webSocketUrl, this.mc.logger, 60000, this.epochTracker, this.socketReferenceKeyPrefix);
284
293
  const duration = common_utils_1.performance.now() - startTime;