@fluidframework/odsp-driver 0.55.2 → 0.56.2

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 (127) hide show
  1. package/dist/checkUrl.d.ts.map +1 -1
  2. package/dist/checkUrl.js +0 -1
  3. package/dist/checkUrl.js.map +1 -1
  4. package/dist/contractsPublic.d.ts +7 -1
  5. package/dist/contractsPublic.d.ts.map +1 -1
  6. package/dist/contractsPublic.js +7 -1
  7. package/dist/contractsPublic.js.map +1 -1
  8. package/dist/createFile.d.ts +3 -3
  9. package/dist/createFile.d.ts.map +1 -1
  10. package/dist/createFile.js +7 -7
  11. package/dist/createFile.js.map +1 -1
  12. package/dist/epochTracker.d.ts +3 -3
  13. package/dist/epochTracker.d.ts.map +1 -1
  14. package/dist/epochTracker.js +20 -8
  15. package/dist/epochTracker.js.map +1 -1
  16. package/dist/fetchSnapshot.d.ts +3 -2
  17. package/dist/fetchSnapshot.d.ts.map +1 -1
  18. package/dist/fetchSnapshot.js +28 -16
  19. package/dist/fetchSnapshot.js.map +1 -1
  20. package/dist/getFileLink.js +4 -4
  21. package/dist/getFileLink.js.map +1 -1
  22. package/dist/getUrlAndHeadersWithAuth.d.ts +1 -1
  23. package/dist/getUrlAndHeadersWithAuth.d.ts.map +1 -1
  24. package/dist/getUrlAndHeadersWithAuth.js +20 -33
  25. package/dist/getUrlAndHeadersWithAuth.js.map +1 -1
  26. package/dist/odspDeltaStorageService.d.ts.map +1 -1
  27. package/dist/odspDeltaStorageService.js +1 -4
  28. package/dist/odspDeltaStorageService.js.map +1 -1
  29. package/dist/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  30. package/dist/odspDocumentServiceFactoryCore.js +2 -2
  31. package/dist/odspDocumentServiceFactoryCore.js.map +1 -1
  32. package/dist/odspDocumentStorageManager.d.ts +1 -0
  33. package/dist/odspDocumentStorageManager.d.ts.map +1 -1
  34. package/dist/odspDocumentStorageManager.js +16 -9
  35. package/dist/odspDocumentStorageManager.js.map +1 -1
  36. package/dist/odspDriverUrlResolver.d.ts.map +1 -1
  37. package/dist/odspDriverUrlResolver.js +5 -2
  38. package/dist/odspDriverUrlResolver.js.map +1 -1
  39. package/dist/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  40. package/dist/odspDriverUrlResolverForShareLink.js +1 -2
  41. package/dist/odspDriverUrlResolverForShareLink.js.map +1 -1
  42. package/dist/odspSummaryUploadManager.d.ts +2 -1
  43. package/dist/odspSummaryUploadManager.d.ts.map +1 -1
  44. package/dist/odspSummaryUploadManager.js +3 -2
  45. package/dist/odspSummaryUploadManager.js.map +1 -1
  46. package/dist/packageVersion.d.ts +1 -1
  47. package/dist/packageVersion.js +1 -1
  48. package/dist/packageVersion.js.map +1 -1
  49. package/dist/prefetchLatestSnapshot.d.ts +2 -1
  50. package/dist/prefetchLatestSnapshot.d.ts.map +1 -1
  51. package/dist/prefetchLatestSnapshot.js +3 -2
  52. package/dist/prefetchLatestSnapshot.js.map +1 -1
  53. package/dist/retryErrorsStorageAdapter.d.ts +1 -1
  54. package/dist/retryErrorsStorageAdapter.d.ts.map +1 -1
  55. package/dist/retryErrorsStorageAdapter.js.map +1 -1
  56. package/lib/checkUrl.d.ts.map +1 -1
  57. package/lib/checkUrl.js +0 -1
  58. package/lib/checkUrl.js.map +1 -1
  59. package/lib/contractsPublic.d.ts +7 -1
  60. package/lib/contractsPublic.d.ts.map +1 -1
  61. package/lib/contractsPublic.js +6 -0
  62. package/lib/contractsPublic.js.map +1 -1
  63. package/lib/createFile.d.ts +3 -3
  64. package/lib/createFile.d.ts.map +1 -1
  65. package/lib/createFile.js +7 -7
  66. package/lib/createFile.js.map +1 -1
  67. package/lib/epochTracker.d.ts +3 -3
  68. package/lib/epochTracker.d.ts.map +1 -1
  69. package/lib/epochTracker.js +21 -9
  70. package/lib/epochTracker.js.map +1 -1
  71. package/lib/fetchSnapshot.d.ts +3 -2
  72. package/lib/fetchSnapshot.d.ts.map +1 -1
  73. package/lib/fetchSnapshot.js +28 -16
  74. package/lib/fetchSnapshot.js.map +1 -1
  75. package/lib/getFileLink.js +4 -4
  76. package/lib/getFileLink.js.map +1 -1
  77. package/lib/getUrlAndHeadersWithAuth.d.ts +1 -1
  78. package/lib/getUrlAndHeadersWithAuth.d.ts.map +1 -1
  79. package/lib/getUrlAndHeadersWithAuth.js +20 -33
  80. package/lib/getUrlAndHeadersWithAuth.js.map +1 -1
  81. package/lib/odspDeltaStorageService.d.ts.map +1 -1
  82. package/lib/odspDeltaStorageService.js +1 -4
  83. package/lib/odspDeltaStorageService.js.map +1 -1
  84. package/lib/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  85. package/lib/odspDocumentServiceFactoryCore.js +2 -2
  86. package/lib/odspDocumentServiceFactoryCore.js.map +1 -1
  87. package/lib/odspDocumentStorageManager.d.ts +1 -0
  88. package/lib/odspDocumentStorageManager.d.ts.map +1 -1
  89. package/lib/odspDocumentStorageManager.js +16 -9
  90. package/lib/odspDocumentStorageManager.js.map +1 -1
  91. package/lib/odspDriverUrlResolver.d.ts.map +1 -1
  92. package/lib/odspDriverUrlResolver.js +5 -2
  93. package/lib/odspDriverUrlResolver.js.map +1 -1
  94. package/lib/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  95. package/lib/odspDriverUrlResolverForShareLink.js +1 -2
  96. package/lib/odspDriverUrlResolverForShareLink.js.map +1 -1
  97. package/lib/odspSummaryUploadManager.d.ts +2 -1
  98. package/lib/odspSummaryUploadManager.d.ts.map +1 -1
  99. package/lib/odspSummaryUploadManager.js +3 -2
  100. package/lib/odspSummaryUploadManager.js.map +1 -1
  101. package/lib/packageVersion.d.ts +1 -1
  102. package/lib/packageVersion.js +1 -1
  103. package/lib/packageVersion.js.map +1 -1
  104. package/lib/prefetchLatestSnapshot.d.ts +2 -1
  105. package/lib/prefetchLatestSnapshot.d.ts.map +1 -1
  106. package/lib/prefetchLatestSnapshot.js +3 -2
  107. package/lib/prefetchLatestSnapshot.js.map +1 -1
  108. package/lib/retryErrorsStorageAdapter.d.ts +1 -1
  109. package/lib/retryErrorsStorageAdapter.d.ts.map +1 -1
  110. package/lib/retryErrorsStorageAdapter.js.map +1 -1
  111. package/package.json +9 -9
  112. package/src/checkUrl.ts +0 -1
  113. package/src/contractsPublic.ts +11 -1
  114. package/src/createFile.ts +16 -4
  115. package/src/epochTracker.ts +21 -6
  116. package/src/fetchSnapshot.ts +33 -16
  117. package/src/getFileLink.ts +7 -2
  118. package/src/getUrlAndHeadersWithAuth.ts +24 -38
  119. package/src/odspDeltaStorageService.ts +1 -3
  120. package/src/odspDocumentServiceFactoryCore.ts +1 -0
  121. package/src/odspDocumentStorageManager.ts +39 -8
  122. package/src/odspDriverUrlResolver.ts +3 -0
  123. package/src/odspDriverUrlResolverForShareLink.ts +1 -2
  124. package/src/odspSummaryUploadManager.ts +6 -1
  125. package/src/packageVersion.ts +1 -1
  126. package/src/prefetchLatestSnapshot.ts +3 -0
  127. package/src/retryErrorsStorageAdapter.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"odspDeltaStorageService.js","sourceRoot":"","sources":["../src/odspDeltaStorageService.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAEH,wEAA8D;AAC9D,+BAAkC;AAElC,+DAAsD;AAItD,+DAGsC;AAGtC,2CAA0D;AAE1D;;GAEG;AACH,MAAa,uBAAuB;IAChC,YACqB,YAAoB,EACpB,eAAgD,EAChD,YAA0B,EAC1B,MAAwB;QAHxB,iBAAY,GAAZ,YAAY,CAAQ;QACpB,oBAAe,GAAf,eAAe,CAAiC;QAChD,iBAAY,GAAZ,YAAY,CAAc;QAC1B,WAAM,GAAN,MAAM,CAAkB;IAE7C,CAAC;IAED;;;;;;OAMG;IACK,KAAK,CAAC,GAAG,CACb,IAAY,EACZ,EAAU,EACV,cAAoC,EACpC,WAAoB;QAEpB,OAAO,uCAA2B,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YACjD,gFAAgF;YAChF,kFAAkF;YAClF,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACxC,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;YAEzE,MAAM,YAAY,GAAG,SAAI,EAAE,CAAC;YAC5B,IAAI,QAAQ,GAAG,KAAK,YAAY,MAAM,CAAC;YACvC,QAAQ,IAAI,yBAAyB,YAAY,MAAM,CAAC;YACxD,QAAQ,IAAI,iCAAiC,CAAC;YAC9C,IAAI,WAAW,KAAK,SAAS,EAAE;gBAC3B,QAAQ,IAAI,gBAAgB,WAAW,MAAM,CAAC;aACjD;YAED,QAAQ,IAAI,cAAc,CAAC;YAC3B,QAAQ,IAAI,SAAS,YAAY,IAAI,CAAC;YACtC,MAAM,OAAO,GAA2B;gBACpC,cAAc,EAAE,gCAAgC,YAAY,EAAE;aACjE,CAAC;YAEF,mGAAmG;YACnG,oGAAoG;YACpG,0GAA0G;YAC1G,6EAA6E;YAC7E,kFAAkF;YAClF,MAAM,KAAK,GAAG,IAAI,0BAAe,EAAE,CAAC;YACpC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;YAErD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,mBAAmB,CACxD,OAAO,EACP;gBACI,OAAO;gBACP,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,KAAK,CAAC,MAAM;aACvB,EACD,KAAK,EACL,IAAI,CACP,CAAC;YACF,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,oBAAoB,GAAG,QAAQ,CAAC,OAAO,CAAC;YAC9C,IAAI,QAAqC,CAAC;YAC1C,IAAI,oBAAoB,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,IAAI,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;gBAChF,QAAQ,GAAI,oBAAoB,CAAC,KAAoC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;aAC1G;iBAAM;gBACH,QAAQ,GAAG,oBAAoB,CAAC,KAAoC,CAAC;aACxE;YAED,IAAI,CAAC,MAAM,CAAC,oBAAoB,6CAC5B,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAC7D,MAAM,EAAE,QAAQ,CAAC,MAAM,EACvB,QAAQ,EAAE,QAAQ,CAAC,QAAQ,IACxB,QAAQ,CAAC,gBAAgB,KAC5B,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACjC,IAAI;gBACJ,EAAE,KACC,cAAc,EACnB,CAAC;YAEH,oGAAoG;YACpG,4GAA4G;YAC5G,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;QAC9C,CAAC,CAAC,CAAC;IACP,CAAC;IAEM,QAAQ,CAAC,IAAY,EAAE,EAAU;QACpC,MAAM,MAAM,GAAG,kBAAkB,CAAC,qBAAqB,IAAI,0BAA0B,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/F,MAAM,WAAW,GAAG,iBAAiB,MAAM,EAAE,CAAC;QAC9C,OAAO,GAAG,IAAI,CAAC,YAAY,GAAG,WAAW,EAAE,CAAC;IAChD,CAAC;CACJ;AA7FD,0DA6FC;AAED,MAAa,yBAAyB;IAGlC,YACY,WAAoD,EAC3C,MAAwB,EACxB,SAAiB,EACjB,WAAmB,EACnB,cAIuC,EACvC,SAA6E,EAC7E,iBAAqD,EACrD,WAAuD;QAXhE,gBAAW,GAAX,WAAW,CAAyC;QAC3C,WAAM,GAAN,MAAM,CAAkB;QACxB,cAAS,GAAT,SAAS,CAAQ;QACjB,gBAAW,GAAX,WAAW,CAAQ;QACnB,mBAAc,GAAd,cAAc,CAIyB;QACvC,cAAS,GAAT,SAAS,CAAoE;QAC7E,sBAAiB,GAAjB,iBAAiB,CAAoC;QACrD,gBAAW,GAAX,WAAW,CAA4C;QAdpE,mBAAc,GAAG,MAAM,CAAC,gBAAgB,CAAC;IAgBjD,CAAC;IAES,gBAAgB,CAAC,MAAc,EAAE,QAAqC,EAAE,IAAY;QAC1F,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;YACvB,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC;YACzC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;YAC/B,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC;YACjD,IAAI,KAAK,KAAK,IAAI,EAAE;gBAChB,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC;gBACjG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;aACvB;YACD,IAAI,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,MAAM,EAAE;gBAC5B,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC;gBACjG,uEAAuE;gBACvE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;aACvB;SACJ;IACL,CAAC;IAEM,aAAa,CAChB,SAAiB,EACjB,OAA2B,EAC3B,WAAyB,EACzB,UAAoB,EACpB,WAAoB;QAEpB,mGAAmG;QACnG,yGAAyG;QACzG,4BAA4B;QAC5B,gGAAgG;QAChG,qBAAM,CAAC,CAAC,UAAU,IAAI,OAAO,KAAK,SAAS,EAAE,KAAK,CAAC,CAAC;QAEpD,IAAI,eAAe,GAAG,CAAC,CAAC;QACxB,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,IAAI,cAAc,GAAG,CAAC,CAAC;QAEvB,MAAM,eAAe,GAAG,KAAK,EAAE,IAAY,EAAE,EAAU,EAAE,cAAoC,EAAE,EAAE;YAC7F,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE;gBACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAC5C,EAAE,CAAC,cAAc,IAAI,IAAI,IAAI,EAAE,CAAC,cAAc,GAAG,EAAE,CAAC,CAAC;gBACzD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;gBAChD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,IAAI,EAAE;oBAC5D,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;oBAC5E,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC;oBAClC,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;iBAC5C;gBACD,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;aAChC;YAED,kDAAkD;YAClD,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAEjC,mFAAmF;YACnF,sCAAsC;YACtC,IAAI,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE;gBAC5B,MAAM,iBAAiB,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACzD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,IAAI,CAAC,CAAC;gBACzD,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE;oBAChC,YAAY,IAAI,iBAAiB,CAAC,MAAM,CAAC;oBACzC,OAAO;wBACH,QAAQ,EAAE,iBAAiB;wBAC3B,aAAa,EAAE,IAAI;qBACtB,CAAC;iBACL;gBACD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;aAC7D;YAED,IAAI,UAAU,EAAE;gBACZ,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;aACjD;YAED,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;YAC7E,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACrD,cAAc,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;YACtC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC/B,OAAO,GAAG,CAAC;QACf,CAAC,CAAC;QAEF,MAAM,MAAM,GAAG,yBAAU,CACrB,KAAK,EAAE,IAAY,EAAE,EAAU,EAAE,cAAoC,EAAE,EAAE;YACrE,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,IAAI,EAAE,EAAE,EAAE,cAAc,CAAC,CAAC;YAC/D,+BAA+B;YAC/B,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC1D,OAAO,MAAM,CAAC;QAClB,CAAC;QACD,uEAAuE;QACvE,0DAA0D;QAC1D,IAAI,CAAC,WAAW,EAChB,SAAS,EAAE,YAAY;QACvB,OAAO,EAAE,YAAY;QACrB,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,MAAM,EACX,WAAW,EACX,WAAW,CACd,CAAC;QAEF,OAAO,6BAAc,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;YACrC,IAAI,MAAM,CAAC,IAAI,IAAI,eAAe,GAAG,YAAY,GAAG,cAAc,KAAK,CAAC,EAAE;gBACtE,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC;oBAC7B,SAAS,EAAE,mBAAmB;oBAC9B,eAAe;oBACf,YAAY;oBACZ,cAAc;iBACjB,CAAC,CAAC;aACN;QACL,CAAC,CAAC,CAAC;IACX,CAAC;CACA;AA5HD,8DA4HC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { default as AbortController } from \"abort-controller\";\nimport { v4 as uuid } from \"uuid\";\nimport { ITelemetryLogger, ITelemetryProperties } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { InstrumentedStorageTokenFetcher } from \"@fluidframework/odsp-driver-definitions\";\nimport { IDeltasFetchResult, IDocumentDeltaStorageService } from \"@fluidframework/driver-definitions\";\nimport {\n requestOps,\n streamObserver,\n} from \"@fluidframework/driver-utils\";\nimport { IDeltaStorageGetResponse, ISequencedDeltaOpMessage } from \"./contracts\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { getWithRetryForTokenRefresh } from \"./odspUtils\";\n\n/**\n * Provides access to the underlying delta storage on the server for sharepoint driver.\n */\nexport class OdspDeltaStorageService {\n constructor(\n private readonly deltaFeedUrl: string,\n private readonly getStorageToken: InstrumentedStorageTokenFetcher,\n private readonly epochTracker: EpochTracker,\n private readonly logger: ITelemetryLogger,\n ) {\n }\n\n /**\n * Retrieves ops from cache\n * @param from - inclusive\n * @param to - exclusive\n * @param telemetryProps - properties to add when issuing telemetry events\n * @returns ops retrieved & info if result was partial (i.e. more is available)\n */\n public async get(\n from: number,\n to: number,\n telemetryProps: ITelemetryProperties,\n fetchReason?: string,\n ): Promise<IDeltasFetchResult> {\n return getWithRetryForTokenRefresh(async (options) => {\n // Note - this call ends up in getSocketStorageDiscovery() and can refresh token\n // Thus it needs to be done before we call getStorageToken() to reduce extra calls\n const baseUrl = this.buildUrl(from, to);\n const storageToken = await this.getStorageToken(options, \"DeltaStorage\");\n\n const formBoundary = uuid();\n let postBody = `--${formBoundary}\\r\\n`;\n postBody += `Authorization: Bearer ${storageToken}\\r\\n`;\n postBody += `X-HTTP-Method-Override: GET\\r\\n`;\n if (fetchReason !== undefined) {\n postBody += `fetchReason: ${fetchReason}\\r\\n`;\n }\n\n postBody += `_post: 1\\r\\n`;\n postBody += `\\r\\n--${formBoundary}--`;\n const headers: {[index: string]: any} = {\n \"Content-Type\": `multipart/form-data;boundary=${formBoundary}`,\n };\n\n // Some request take a long time (1-2 minutes) to complete, where telemetry shows very small amount\n // of time spent on server, and usually small payload sizes. I.e. all the time is spent somewhere in\n // networking. Even bigger problem - a lot of requests timeout (based on cursory look - after 1-2 minutes)\n // So adding some timeout to ensure we retry again in hope of faster success.\n // Please see https://github.com/microsoft/FluidFramework/issues/6997 for details.\n const abort = new AbortController();\n const timer = setTimeout(() => abort.abort(), 30000);\n\n const response = await this.epochTracker.fetchAndParseAsJSON<IDeltaStorageGetResponse>(\n baseUrl,\n {\n headers,\n body: postBody,\n method: \"POST\",\n signal: abort.signal,\n },\n \"ops\",\n true,\n );\n clearTimeout(timer);\n const deltaStorageResponse = response.content;\n let messages: ISequencedDocumentMessage[];\n if (deltaStorageResponse.value.length > 0 && \"op\" in deltaStorageResponse.value[0]) {\n messages = (deltaStorageResponse.value as ISequencedDeltaOpMessage[]).map((operation) => operation.op);\n } else {\n messages = deltaStorageResponse.value as ISequencedDocumentMessage[];\n }\n\n this.logger.sendPerformanceEvent({\n eventName: \"OpsFetch\",\n headers: Object.keys(headers).length !== 0 ? true : undefined,\n length: messages.length,\n duration: response.duration, // this duration for single attempt!\n ...response.commonSpoHeaders,\n attempts: options.refresh ? 2 : 1,\n from,\n to,\n ...telemetryProps,\n });\n\n // It is assumed that server always returns all the ops that it has in the range that was requested.\n // This may change in the future, if so, we need to adjust and receive \"end\" value from server in such case.\n return { messages, partialResult: false };\n });\n }\n\n public buildUrl(from: number, to: number) {\n const filter = encodeURIComponent(`sequenceNumber ge ${from} and sequenceNumber le ${to - 1}`);\n const queryString = `?ump=1&filter=${filter}`;\n return `${this.deltaFeedUrl}${queryString}`;\n }\n}\n\nexport class OdspDeltaStorageWithCache implements IDocumentDeltaStorageService {\n private firstCacheMiss = Number.MAX_SAFE_INTEGER;\n\n public constructor(\n private snapshotOps: ISequencedDocumentMessage[] | undefined,\n private readonly logger: ITelemetryLogger,\n private readonly batchSize: number,\n private readonly concurrency: number,\n private readonly getFromStorage: (\n from: number,\n to: number,\n telemetryProps: ITelemetryProperties,\n fetchReason?: string) => Promise<IDeltasFetchResult>,\n private readonly getCached: (from: number, to: number) => Promise<ISequencedDocumentMessage[]>,\n private readonly requestFromSocket: (from: number, to: number) => void,\n private readonly opsReceived: (ops: ISequencedDocumentMessage[]) => void,\n ) {\n }\n\n protected validateMessages(reason: string, messages: ISequencedDocumentMessage[], from: number) {\n if (messages.length !== 0) {\n const start = messages[0].sequenceNumber;\n const length = messages.length;\n const last = messages[length - 1].sequenceNumber;\n if (start !== from) {\n this.logger.sendErrorEvent({ eventName: \"OpsFetchViolation\", reason, from, start, last, length});\n messages.length = 0;\n }\n if (last + 1 !== from + length) {\n this.logger.sendErrorEvent({ eventName: \"OpsFetchViolation\", reason, from, start, last, length});\n // we can do better here by finding consecutive sub-block and return it\n messages.length = 0;\n }\n }\n }\n\n public fetchMessages(\n fromTotal: number,\n toTotal: number | undefined,\n abortSignal?: AbortSignal,\n cachedOnly?: boolean,\n fetchReason?: string)\n {\n // We do not control what's in the cache. Current API assumes that fetchMessages() keeps banging on\n // storage / cache until it gets ops it needs. This would result in deadlock if fixed range is asked from\n // cache and it's not there.\n // Better implementation would be to return only what we have in cache, but that also breaks API\n assert(!cachedOnly || toTotal === undefined, 0x1e3);\n\n let opsFromSnapshot = 0;\n let opsFromCache = 0;\n let opsFromStorage = 0;\n\n const requestCallback = async (from: number, to: number, telemetryProps: ITelemetryProperties) => {\n if (this.snapshotOps !== undefined && this.snapshotOps.length !== 0) {\n const messages = this.snapshotOps.filter((op) =>\n op.sequenceNumber >= from && op.sequenceNumber < to);\n this.validateMessages(\"cached\", messages, from);\n if (messages.length > 0 && messages[0].sequenceNumber === from) {\n this.snapshotOps = this.snapshotOps.filter((op) => op.sequenceNumber >= to);\n opsFromSnapshot = messages.length;\n return { messages, partialResult: true };\n }\n this.snapshotOps = undefined;\n }\n\n // Kick out request to PUSH for ops if it has them\n this.requestFromSocket(from, to);\n\n // Cache in normal flow is continuous. Once there is a miss, stop consulting cache.\n // This saves a bit of processing time\n if (from < this.firstCacheMiss) {\n const messagesFromCache = await this.getCached(from, to);\n this.validateMessages(\"cached\", messagesFromCache, from);\n if (messagesFromCache.length !== 0) {\n opsFromCache += messagesFromCache.length;\n return {\n messages: messagesFromCache,\n partialResult: true,\n };\n }\n this.firstCacheMiss = Math.min(this.firstCacheMiss, from);\n }\n\n if (cachedOnly) {\n return { messages: [], partialResult: false };\n }\n\n const ops = await this.getFromStorage(from, to, telemetryProps, fetchReason);\n this.validateMessages(\"storage\", ops.messages, from);\n opsFromStorage += ops.messages.length;\n this.opsReceived(ops.messages);\n return ops;\n };\n\n const stream = requestOps(\n async (from: number, to: number, telemetryProps: ITelemetryProperties) => {\n const result = await requestCallback(from, to, telemetryProps);\n // Catch all case, just in case\n this.validateMessages(\"catch all\", result.messages, from);\n return result;\n },\n // Staging: starting with no concurrency, listening for feedback first.\n // In future releases we will switch to actual concurrency\n this.concurrency,\n fromTotal, // inclusive\n toTotal, // exclusive\n this.batchSize,\n this.logger,\n abortSignal,\n fetchReason,\n );\n\n return streamObserver(stream, (result) => {\n if (result.done && opsFromSnapshot + opsFromCache + opsFromStorage !== 0) {\n this.logger.sendPerformanceEvent({\n eventName: \"CacheOpsRetrieved\",\n opsFromSnapshot,\n opsFromCache,\n opsFromStorage,\n });\n }\n });\n}\n}\n"]}
1
+ {"version":3,"file":"odspDeltaStorageService.js","sourceRoot":"","sources":["../src/odspDeltaStorageService.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 { default as AbortController } from \"abort-controller\";\nimport { v4 as uuid } from \"uuid\";\nimport { ITelemetryLogger, ITelemetryProperties } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { InstrumentedStorageTokenFetcher } from \"@fluidframework/odsp-driver-definitions\";\nimport { IDeltasFetchResult, IDocumentDeltaStorageService } from \"@fluidframework/driver-definitions\";\nimport {\n requestOps,\n streamObserver,\n} from \"@fluidframework/driver-utils\";\nimport { IDeltaStorageGetResponse, ISequencedDeltaOpMessage } from \"./contracts\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { getWithRetryForTokenRefresh } from \"./odspUtils\";\n\n/**\n * Provides access to the underlying delta storage on the server for sharepoint driver.\n */\nexport class OdspDeltaStorageService {\n constructor(\n private readonly deltaFeedUrl: string,\n private readonly getStorageToken: InstrumentedStorageTokenFetcher,\n private readonly epochTracker: EpochTracker,\n private readonly logger: ITelemetryLogger,\n ) {\n }\n\n /**\n * Retrieves ops from cache\n * @param from - inclusive\n * @param to - exclusive\n * @param telemetryProps - properties to add when issuing telemetry events\n * @returns ops retrieved & info if result was partial (i.e. more is available)\n */\n public async get(\n from: number,\n to: number,\n telemetryProps: ITelemetryProperties,\n fetchReason?: string,\n ): Promise<IDeltasFetchResult> {\n return getWithRetryForTokenRefresh(async (options) => {\n // Note - this call ends up in getSocketStorageDiscovery() and can refresh token\n // Thus it needs to be done before we call getStorageToken() to reduce extra calls\n const baseUrl = this.buildUrl(from, to);\n const storageToken = await this.getStorageToken(options, \"DeltaStorage\");\n\n const formBoundary = uuid();\n let postBody = `--${formBoundary}\\r\\n`;\n postBody += `Authorization: Bearer ${storageToken}\\r\\n`;\n postBody += `X-HTTP-Method-Override: GET\\r\\n`;\n\n postBody += `_post: 1\\r\\n`;\n postBody += `\\r\\n--${formBoundary}--`;\n const headers: {[index: string]: any} = {\n \"Content-Type\": `multipart/form-data;boundary=${formBoundary}`,\n };\n\n // Some request take a long time (1-2 minutes) to complete, where telemetry shows very small amount\n // of time spent on server, and usually small payload sizes. I.e. all the time is spent somewhere in\n // networking. Even bigger problem - a lot of requests timeout (based on cursory look - after 1-2 minutes)\n // So adding some timeout to ensure we retry again in hope of faster success.\n // Please see https://github.com/microsoft/FluidFramework/issues/6997 for details.\n const abort = new AbortController();\n const timer = setTimeout(() => abort.abort(), 30000);\n\n const response = await this.epochTracker.fetchAndParseAsJSON<IDeltaStorageGetResponse>(\n baseUrl,\n {\n headers,\n body: postBody,\n method: \"POST\",\n signal: abort.signal,\n },\n \"ops\",\n true,\n fetchReason,\n );\n clearTimeout(timer);\n const deltaStorageResponse = response.content;\n let messages: ISequencedDocumentMessage[];\n if (deltaStorageResponse.value.length > 0 && \"op\" in deltaStorageResponse.value[0]) {\n messages = (deltaStorageResponse.value as ISequencedDeltaOpMessage[]).map((operation) => operation.op);\n } else {\n messages = deltaStorageResponse.value as ISequencedDocumentMessage[];\n }\n\n this.logger.sendPerformanceEvent({\n eventName: \"OpsFetch\",\n headers: Object.keys(headers).length !== 0 ? true : undefined,\n length: messages.length,\n duration: response.duration, // this duration for single attempt!\n ...response.commonSpoHeaders,\n attempts: options.refresh ? 2 : 1,\n from,\n to,\n ...telemetryProps,\n });\n\n // It is assumed that server always returns all the ops that it has in the range that was requested.\n // This may change in the future, if so, we need to adjust and receive \"end\" value from server in such case.\n return { messages, partialResult: false };\n });\n }\n\n public buildUrl(from: number, to: number) {\n const filter = encodeURIComponent(`sequenceNumber ge ${from} and sequenceNumber le ${to - 1}`);\n const queryString = `?ump=1&filter=${filter}`;\n return `${this.deltaFeedUrl}${queryString}`;\n }\n}\n\nexport class OdspDeltaStorageWithCache implements IDocumentDeltaStorageService {\n private firstCacheMiss = Number.MAX_SAFE_INTEGER;\n\n public constructor(\n private snapshotOps: ISequencedDocumentMessage[] | undefined,\n private readonly logger: ITelemetryLogger,\n private readonly batchSize: number,\n private readonly concurrency: number,\n private readonly getFromStorage: (\n from: number,\n to: number,\n telemetryProps: ITelemetryProperties,\n fetchReason?: string) => Promise<IDeltasFetchResult>,\n private readonly getCached: (from: number, to: number) => Promise<ISequencedDocumentMessage[]>,\n private readonly requestFromSocket: (from: number, to: number) => void,\n private readonly opsReceived: (ops: ISequencedDocumentMessage[]) => void,\n ) {\n }\n\n protected validateMessages(reason: string, messages: ISequencedDocumentMessage[], from: number) {\n if (messages.length !== 0) {\n const start = messages[0].sequenceNumber;\n const length = messages.length;\n const last = messages[length - 1].sequenceNumber;\n if (start !== from) {\n this.logger.sendErrorEvent({ eventName: \"OpsFetchViolation\", reason, from, start, last, length});\n messages.length = 0;\n }\n if (last + 1 !== from + length) {\n this.logger.sendErrorEvent({ eventName: \"OpsFetchViolation\", reason, from, start, last, length});\n // we can do better here by finding consecutive sub-block and return it\n messages.length = 0;\n }\n }\n }\n\n public fetchMessages(\n fromTotal: number,\n toTotal: number | undefined,\n abortSignal?: AbortSignal,\n cachedOnly?: boolean,\n fetchReason?: string)\n {\n // We do not control what's in the cache. Current API assumes that fetchMessages() keeps banging on\n // storage / cache until it gets ops it needs. This would result in deadlock if fixed range is asked from\n // cache and it's not there.\n // Better implementation would be to return only what we have in cache, but that also breaks API\n assert(!cachedOnly || toTotal === undefined, 0x1e3);\n\n let opsFromSnapshot = 0;\n let opsFromCache = 0;\n let opsFromStorage = 0;\n\n const requestCallback = async (from: number, to: number, telemetryProps: ITelemetryProperties) => {\n if (this.snapshotOps !== undefined && this.snapshotOps.length !== 0) {\n const messages = this.snapshotOps.filter((op) =>\n op.sequenceNumber >= from && op.sequenceNumber < to);\n this.validateMessages(\"cached\", messages, from);\n if (messages.length > 0 && messages[0].sequenceNumber === from) {\n this.snapshotOps = this.snapshotOps.filter((op) => op.sequenceNumber >= to);\n opsFromSnapshot = messages.length;\n return { messages, partialResult: true };\n }\n this.snapshotOps = undefined;\n }\n\n // Kick out request to PUSH for ops if it has them\n this.requestFromSocket(from, to);\n\n // Cache in normal flow is continuous. Once there is a miss, stop consulting cache.\n // This saves a bit of processing time\n if (from < this.firstCacheMiss) {\n const messagesFromCache = await this.getCached(from, to);\n this.validateMessages(\"cached\", messagesFromCache, from);\n if (messagesFromCache.length !== 0) {\n opsFromCache += messagesFromCache.length;\n return {\n messages: messagesFromCache,\n partialResult: true,\n };\n }\n this.firstCacheMiss = Math.min(this.firstCacheMiss, from);\n }\n\n if (cachedOnly) {\n return { messages: [], partialResult: false };\n }\n\n const ops = await this.getFromStorage(from, to, telemetryProps, fetchReason);\n this.validateMessages(\"storage\", ops.messages, from);\n opsFromStorage += ops.messages.length;\n this.opsReceived(ops.messages);\n return ops;\n };\n\n const stream = requestOps(\n async (from: number, to: number, telemetryProps: ITelemetryProperties) => {\n const result = await requestCallback(from, to, telemetryProps);\n // Catch all case, just in case\n this.validateMessages(\"catch all\", result.messages, from);\n return result;\n },\n // Staging: starting with no concurrency, listening for feedback first.\n // In future releases we will switch to actual concurrency\n this.concurrency,\n fromTotal, // inclusive\n toTotal, // exclusive\n this.batchSize,\n this.logger,\n abortSignal,\n fetchReason,\n );\n\n return streamObserver(stream, (result) => {\n if (result.done && opsFromSnapshot + opsFromCache + opsFromStorage !== 0) {\n this.logger.sendPerformanceEvent({\n eventName: \"CacheOpsRetrieved\",\n opsFromSnapshot,\n opsFromCache,\n opsFromStorage,\n });\n }\n });\n}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"odspDocumentServiceFactoryCore.d.ts","sourceRoot":"","sources":["../src/odspDocumentServiceFactoryCore.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EACH,gBAAgB,EAChB,uBAAuB,EACvB,YAAY,EACf,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAMpE,OAAO,EAEH,6BAA6B,EAC7B,YAAY,EACZ,eAAe,EACf,iBAAiB,EAEpB,MAAM,yCAAyC,CAAC;AAcjD;;;;;;GAMG;AACH,qBAAa,8BAA+B,YAAW,uBAAuB;IAiFtE,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,SAAS,CAAC,cAAc,EAAE,eAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU;IApF/B,SAAgB,YAAY,iBAAiB;IAE7C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA4B;IAC/D,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAS;IAEtC,eAAe,CACxB,gBAAgB,EAAE,YAAY,GAAG,SAAS,EAC1C,oBAAoB,EAAE,YAAY,EAClC,MAAM,CAAC,EAAE,oBAAoB,GAC9B,OAAO,CAAC,gBAAgB,CAAC;IA4D5B;;;;;;;;;OASG;gBAEkB,eAAe,EAAE,YAAY,CAAC,6BAA6B,CAAC,EAC5D,iBAAiB,EAAE,YAAY,CAAC,6BAA6B,CAAC,GAAG,SAAS,EAC1E,iBAAiB,EAAE,MAAM,OAAO,CAAC,oBAAoB,CAAC,EAC7D,cAAc,GAAE,eAA4C,EACrD,UAAU,GAAE,iBAAsB;IAQ1C,qBAAqB,CAC9B,WAAW,EAAE,YAAY,EACzB,MAAM,CAAC,EAAE,oBAAoB,GAC9B,OAAO,CAAC,gBAAgB,CAAC;YAId,yBAAyB;CAwC1C"}
1
+ {"version":3,"file":"odspDocumentServiceFactoryCore.d.ts","sourceRoot":"","sources":["../src/odspDocumentServiceFactoryCore.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EACH,gBAAgB,EAChB,uBAAuB,EACvB,YAAY,EACf,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAMpE,OAAO,EAEH,6BAA6B,EAC7B,YAAY,EACZ,eAAe,EACf,iBAAiB,EAEpB,MAAM,yCAAyC,CAAC;AAcjD;;;;;;GAMG;AACH,qBAAa,8BAA+B,YAAW,uBAAuB;IAkFtE,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,SAAS,CAAC,cAAc,EAAE,eAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU;IArF/B,SAAgB,YAAY,iBAAiB;IAE7C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA4B;IAC/D,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAS;IAEtC,eAAe,CACxB,gBAAgB,EAAE,YAAY,GAAG,SAAS,EAC1C,oBAAoB,EAAE,YAAY,EAClC,MAAM,CAAC,EAAE,oBAAoB,GAC9B,OAAO,CAAC,gBAAgB,CAAC;IA6D5B;;;;;;;;;OASG;gBAEkB,eAAe,EAAE,YAAY,CAAC,6BAA6B,CAAC,EAC5D,iBAAiB,EAAE,YAAY,CAAC,6BAA6B,CAAC,GAAG,SAAS,EAC1E,iBAAiB,EAAE,MAAM,OAAO,CAAC,oBAAoB,CAAC,EAC7D,cAAc,GAAE,eAA4C,EACrD,UAAU,GAAE,iBAAsB;IAQ1C,qBAAqB,CAC9B,WAAW,EAAE,YAAY,EACzB,MAAM,CAAC,EAAE,oBAAoB,GAC9B,OAAO,CAAC,gBAAgB,CAAC;YAId,yBAAyB;CAwC1C"}
@@ -70,8 +70,8 @@ class OdspDocumentServiceFactoryCore {
70
70
  eventName: "CreateNew",
71
71
  isWithSummaryUpload: true,
72
72
  }, async (event) => {
73
- var _a;
74
- odspResolvedUrl = await createFile_1.createNewFluidFile(odspUtils_1.toInstrumentedOdspTokenFetcher(odspLogger, odspResolvedUrl, this.getStorageToken, true /* throwOnNullToken */), newFileInfo, odspLogger, createNewSummary, cacheAndTracker.epochTracker, fileEntry, (_a = this.hostPolicy.cacheCreateNewSummary) !== null && _a !== void 0 ? _a : true);
73
+ var _a, _b;
74
+ odspResolvedUrl = await createFile_1.createNewFluidFile(odspUtils_1.toInstrumentedOdspTokenFetcher(odspLogger, odspResolvedUrl, this.getStorageToken, true /* throwOnNullToken */), newFileInfo, odspLogger, createNewSummary, cacheAndTracker.epochTracker, fileEntry, (_a = this.hostPolicy.cacheCreateNewSummary) !== null && _a !== void 0 ? _a : true, !!((_b = this.hostPolicy.sessionOptions) === null || _b === void 0 ? void 0 : _b.forceAccessTokenViaAuthorizationHeader));
75
75
  const docService = this.createDocumentServiceCore(odspResolvedUrl, odspLogger, cacheAndTracker);
76
76
  event.end({
77
77
  docId: odspResolvedUrl.hashedDocumentId,
@@ -1 +1 @@
1
- {"version":3,"file":"odspDocumentServiceFactoryCore.js","sourceRoot":"","sources":["../src/odspDocumentServiceFactoryCore.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 { ITelemetryBaseLogger } from \"@fluidframework/common-definitions\";\nimport {\n IDocumentService,\n IDocumentServiceFactory,\n IResolvedUrl,\n} from \"@fluidframework/driver-definitions\";\nimport { ISummaryTree } from \"@fluidframework/protocol-definitions\";\nimport {\n TelemetryLogger,\n PerformanceEvent,\n} from \"@fluidframework/telemetry-utils\";\nimport { ensureFluidResolvedUrl } from \"@fluidframework/driver-utils\";\nimport {\n TokenFetchOptions,\n OdspResourceTokenFetchOptions,\n TokenFetcher,\n IPersistedCache,\n HostStoragePolicy,\n IFileEntry,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { v4 as uuid } from \"uuid\";\nimport {\n LocalPersistentCache,\n NonPersistentCache,\n} from \"./odspCache\";\nimport {\n createOdspCacheAndTracker,\n ICacheAndTracker,\n} from \"./epochTracker\";\nimport { OdspDocumentService } from \"./odspDocumentService\";\nimport { INewFileInfo, getOdspResolvedUrl, createOdspLogger, toInstrumentedOdspTokenFetcher } from \"./odspUtils\";\nimport { createNewFluidFile } from \"./createFile\";\n\n/**\n * Factory for creating the sharepoint document service. Use this if you want to\n * use the sharepoint implementation.\n *\n * This constructor should be used by environments that support dynamic imports and that wish\n * to leverage code splitting as a means to keep bundles as small as possible.\n */\nexport class OdspDocumentServiceFactoryCore implements IDocumentServiceFactory {\n public readonly protocolName = \"fluid-odsp:\";\n\n private readonly nonPersistentCache = new NonPersistentCache();\n private readonly socketReferenceKeyPrefix?: string;\n\n public async createContainer(\n createNewSummary: ISummaryTree | undefined,\n createNewResolvedUrl: IResolvedUrl,\n logger?: ITelemetryBaseLogger,\n ): Promise<IDocumentService> {\n ensureFluidResolvedUrl(createNewResolvedUrl);\n\n let odspResolvedUrl = getOdspResolvedUrl(createNewResolvedUrl);\n const [, queryString] = odspResolvedUrl.url.split(\"?\");\n\n const searchParams = new URLSearchParams(queryString);\n const filePath = searchParams.get(\"path\");\n if (filePath === undefined || filePath === null) {\n throw new Error(\"File path should be provided!!\");\n }\n const newFileInfo: INewFileInfo = {\n driveId: odspResolvedUrl.driveId,\n siteUrl: odspResolvedUrl.siteUrl,\n filePath,\n filename: odspResolvedUrl.fileName,\n // set createLinkType to undefined if enableShareLinkWithCreate is set to false,\n // so that share link creation with create file can be enabled\n createLinkType: this.hostPolicy.enableShareLinkWithCreate ?\n odspResolvedUrl.shareLinkInfo?.createLink?.type : undefined,\n };\n\n const odspLogger = createOdspLogger(logger);\n\n const fileEntry: IFileEntry = { resolvedUrl: odspResolvedUrl, docId: odspResolvedUrl.hashedDocumentId };\n const cacheAndTracker = createOdspCacheAndTracker(\n this.persistedCache,\n this.nonPersistentCache,\n fileEntry,\n odspLogger);\n\n return PerformanceEvent.timedExecAsync(\n odspLogger,\n {\n eventName: \"CreateNew\",\n isWithSummaryUpload: true,\n },\n async (event) => {\n odspResolvedUrl = await createNewFluidFile(\n toInstrumentedOdspTokenFetcher(\n odspLogger,\n odspResolvedUrl,\n this.getStorageToken,\n true /* throwOnNullToken */,\n ),\n newFileInfo,\n odspLogger,\n createNewSummary,\n cacheAndTracker.epochTracker,\n fileEntry,\n this.hostPolicy.cacheCreateNewSummary ?? true,\n );\n const docService = this.createDocumentServiceCore(odspResolvedUrl, odspLogger, cacheAndTracker);\n event.end({\n docId: odspResolvedUrl.hashedDocumentId,\n });\n return docService;\n });\n }\n\n /**\n * @param getStorageToken - function that can provide the storage token for a given site. This is\n * is also referred to as the \"Vroom\" token in SPO.\n * @param getWebsocketToken - function that can provide a token for accessing the web socket. This is also\n * to as the \"Push\" token in SPO. If undefined then websocket token is expected to be returned with joinSession\n * response payload.\n * @param storageFetchWrapper - if not provided FetchWrapper will be used\n * @param deltasFetchWrapper - if not provided FetchWrapper will be used\n * @param persistedCache - PersistedCache provided by host for use in this session.\n */\n constructor(\n private readonly getStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n private readonly getWebsocketToken: TokenFetcher<OdspResourceTokenFetchOptions> | undefined,\n private readonly getSocketIOClient: () => Promise<SocketIOClientStatic>,\n protected persistedCache: IPersistedCache = new LocalPersistentCache(),\n private readonly hostPolicy: HostStoragePolicy = {},\n ) {\n if (this.hostPolicy.isolateSocketCache === true) {\n // create the key to separate the socket reuse cache\n this.socketReferenceKeyPrefix = uuid();\n }\n }\n\n public async createDocumentService(\n resolvedUrl: IResolvedUrl,\n logger?: ITelemetryBaseLogger,\n ): Promise<IDocumentService> {\n return this.createDocumentServiceCore(resolvedUrl, createOdspLogger(logger));\n }\n\n private async createDocumentServiceCore(\n resolvedUrl: IResolvedUrl,\n odspLogger: TelemetryLogger,\n cacheAndTrackerArg?: ICacheAndTracker,\n ): Promise<IDocumentService> {\n const odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);\n const cacheAndTracker = cacheAndTrackerArg ?? createOdspCacheAndTracker(\n this.persistedCache,\n this.nonPersistentCache,\n { resolvedUrl: odspResolvedUrl, docId: odspResolvedUrl.hashedDocumentId },\n odspLogger);\n\n const storageTokenFetcher = toInstrumentedOdspTokenFetcher(\n odspLogger,\n odspResolvedUrl,\n this.getStorageToken,\n true /* throwOnNullToken */,\n );\n\n const webSocketTokenFetcher = this.getWebsocketToken === undefined\n ? undefined\n : async (options: TokenFetchOptions) => toInstrumentedOdspTokenFetcher(\n odspLogger,\n odspResolvedUrl,\n this.getWebsocketToken!,\n false /* throwOnNullToken */,\n )(options, \"GetWebsocketToken\");\n\n return OdspDocumentService.create(\n resolvedUrl,\n storageTokenFetcher,\n webSocketTokenFetcher,\n odspLogger,\n this.getSocketIOClient,\n cacheAndTracker.cache,\n this.hostPolicy,\n cacheAndTracker.epochTracker,\n this.socketReferenceKeyPrefix,\n );\n }\n}\n"]}
1
+ {"version":3,"file":"odspDocumentServiceFactoryCore.js","sourceRoot":"","sources":["../src/odspDocumentServiceFactoryCore.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 { ITelemetryBaseLogger } from \"@fluidframework/common-definitions\";\nimport {\n IDocumentService,\n IDocumentServiceFactory,\n IResolvedUrl,\n} from \"@fluidframework/driver-definitions\";\nimport { ISummaryTree } from \"@fluidframework/protocol-definitions\";\nimport {\n TelemetryLogger,\n PerformanceEvent,\n} from \"@fluidframework/telemetry-utils\";\nimport { ensureFluidResolvedUrl } from \"@fluidframework/driver-utils\";\nimport {\n TokenFetchOptions,\n OdspResourceTokenFetchOptions,\n TokenFetcher,\n IPersistedCache,\n HostStoragePolicy,\n IFileEntry,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { v4 as uuid } from \"uuid\";\nimport {\n LocalPersistentCache,\n NonPersistentCache,\n} from \"./odspCache\";\nimport {\n createOdspCacheAndTracker,\n ICacheAndTracker,\n} from \"./epochTracker\";\nimport { OdspDocumentService } from \"./odspDocumentService\";\nimport { INewFileInfo, getOdspResolvedUrl, createOdspLogger, toInstrumentedOdspTokenFetcher } from \"./odspUtils\";\nimport { createNewFluidFile } from \"./createFile\";\n\n/**\n * Factory for creating the sharepoint document service. Use this if you want to\n * use the sharepoint implementation.\n *\n * This constructor should be used by environments that support dynamic imports and that wish\n * to leverage code splitting as a means to keep bundles as small as possible.\n */\nexport class OdspDocumentServiceFactoryCore implements IDocumentServiceFactory {\n public readonly protocolName = \"fluid-odsp:\";\n\n private readonly nonPersistentCache = new NonPersistentCache();\n private readonly socketReferenceKeyPrefix?: string;\n\n public async createContainer(\n createNewSummary: ISummaryTree | undefined,\n createNewResolvedUrl: IResolvedUrl,\n logger?: ITelemetryBaseLogger,\n ): Promise<IDocumentService> {\n ensureFluidResolvedUrl(createNewResolvedUrl);\n\n let odspResolvedUrl = getOdspResolvedUrl(createNewResolvedUrl);\n const [, queryString] = odspResolvedUrl.url.split(\"?\");\n\n const searchParams = new URLSearchParams(queryString);\n const filePath = searchParams.get(\"path\");\n if (filePath === undefined || filePath === null) {\n throw new Error(\"File path should be provided!!\");\n }\n const newFileInfo: INewFileInfo = {\n driveId: odspResolvedUrl.driveId,\n siteUrl: odspResolvedUrl.siteUrl,\n filePath,\n filename: odspResolvedUrl.fileName,\n // set createLinkType to undefined if enableShareLinkWithCreate is set to false,\n // so that share link creation with create file can be enabled\n createLinkType: this.hostPolicy.enableShareLinkWithCreate ?\n odspResolvedUrl.shareLinkInfo?.createLink?.type : undefined,\n };\n\n const odspLogger = createOdspLogger(logger);\n\n const fileEntry: IFileEntry = { resolvedUrl: odspResolvedUrl, docId: odspResolvedUrl.hashedDocumentId };\n const cacheAndTracker = createOdspCacheAndTracker(\n this.persistedCache,\n this.nonPersistentCache,\n fileEntry,\n odspLogger);\n\n return PerformanceEvent.timedExecAsync(\n odspLogger,\n {\n eventName: \"CreateNew\",\n isWithSummaryUpload: true,\n },\n async (event) => {\n odspResolvedUrl = await createNewFluidFile(\n toInstrumentedOdspTokenFetcher(\n odspLogger,\n odspResolvedUrl,\n this.getStorageToken,\n true /* throwOnNullToken */,\n ),\n newFileInfo,\n odspLogger,\n createNewSummary,\n cacheAndTracker.epochTracker,\n fileEntry,\n this.hostPolicy.cacheCreateNewSummary ?? true,\n !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n );\n const docService = this.createDocumentServiceCore(odspResolvedUrl, odspLogger, cacheAndTracker);\n event.end({\n docId: odspResolvedUrl.hashedDocumentId,\n });\n return docService;\n });\n }\n\n /**\n * @param getStorageToken - function that can provide the storage token for a given site. This is\n * is also referred to as the \"Vroom\" token in SPO.\n * @param getWebsocketToken - function that can provide a token for accessing the web socket. This is also\n * to as the \"Push\" token in SPO. If undefined then websocket token is expected to be returned with joinSession\n * response payload.\n * @param storageFetchWrapper - if not provided FetchWrapper will be used\n * @param deltasFetchWrapper - if not provided FetchWrapper will be used\n * @param persistedCache - PersistedCache provided by host for use in this session.\n */\n constructor(\n private readonly getStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n private readonly getWebsocketToken: TokenFetcher<OdspResourceTokenFetchOptions> | undefined,\n private readonly getSocketIOClient: () => Promise<SocketIOClientStatic>,\n protected persistedCache: IPersistedCache = new LocalPersistentCache(),\n private readonly hostPolicy: HostStoragePolicy = {},\n ) {\n if (this.hostPolicy.isolateSocketCache === true) {\n // create the key to separate the socket reuse cache\n this.socketReferenceKeyPrefix = uuid();\n }\n }\n\n public async createDocumentService(\n resolvedUrl: IResolvedUrl,\n logger?: ITelemetryBaseLogger,\n ): Promise<IDocumentService> {\n return this.createDocumentServiceCore(resolvedUrl, createOdspLogger(logger));\n }\n\n private async createDocumentServiceCore(\n resolvedUrl: IResolvedUrl,\n odspLogger: TelemetryLogger,\n cacheAndTrackerArg?: ICacheAndTracker,\n ): Promise<IDocumentService> {\n const odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);\n const cacheAndTracker = cacheAndTrackerArg ?? createOdspCacheAndTracker(\n this.persistedCache,\n this.nonPersistentCache,\n { resolvedUrl: odspResolvedUrl, docId: odspResolvedUrl.hashedDocumentId },\n odspLogger);\n\n const storageTokenFetcher = toInstrumentedOdspTokenFetcher(\n odspLogger,\n odspResolvedUrl,\n this.getStorageToken,\n true /* throwOnNullToken */,\n );\n\n const webSocketTokenFetcher = this.getWebsocketToken === undefined\n ? undefined\n : async (options: TokenFetchOptions) => toInstrumentedOdspTokenFetcher(\n odspLogger,\n odspResolvedUrl,\n this.getWebsocketToken!,\n false /* throwOnNullToken */,\n )(options, \"GetWebsocketToken\");\n\n return OdspDocumentService.create(\n resolvedUrl,\n storageTokenFetcher,\n webSocketTokenFetcher,\n odspLogger,\n this.getSocketIOClient,\n cacheAndTracker.cache,\n this.hostPolicy,\n cacheAndTracker.epochTracker,\n this.socketReferenceKeyPrefix,\n );\n }\n}\n"]}
@@ -22,6 +22,7 @@ export declare class OdspDocumentStorageService implements IDocumentStorageServi
22
22
  readonly policies: {
23
23
  caching: LoaderCachingPolicy;
24
24
  minBlobSize: number;
25
+ maximumCacheDurationMs: number;
25
26
  };
26
27
  private readonly commitCache;
27
28
  private readonly attributesBlobHandles;
@@ -1 +1 @@
1
- {"version":3,"file":"odspDocumentStorageManager.d.ts","sourceRoot":"","sources":["../src/odspDocumentStorageManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"odspDocumentStorageManager.d.ts","sourceRoot":"","sources":["../src/odspDocumentStorageManager.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,7 @@ const odsp_driver_definitions_1 = require("@fluidframework/odsp-driver-definitio
13
13
  const fetchSnapshot_1 = require("./fetchSnapshot");
14
14
  const getUrlAndHeadersWithAuth_1 = require("./getUrlAndHeadersWithAuth");
15
15
  const odspUtils_1 = require("./odspUtils");
16
+ const epochTracker_1 = require("./epochTracker");
16
17
  const odspSummaryUploadManager_1 = require("./odspSummaryUploadManager");
17
18
  /* eslint-disable max-len */
18
19
  // An implementation of Promise.race that gives you the winner of the promise race
@@ -114,6 +115,7 @@ class BlobCache {
114
115
  }
115
116
  class OdspDocumentStorageService {
116
117
  constructor(odspResolvedUrl, getStorageToken, logger, fetchFullSnapshot, cache, hostPolicy, epochTracker, flushCallback) {
118
+ var _a;
117
119
  this.odspResolvedUrl = odspResolvedUrl;
118
120
  this.getStorageToken = getStorageToken;
119
121
  this.logger = logger;
@@ -136,6 +138,7 @@ class OdspDocumentStorageService {
136
138
  // Note that duplication of content should not have significant impact for bytes over wire as
137
139
  // compression of http payload mostly takes care of it, but it does impact storage size and in-memory sizes.
138
140
  minBlobSize: 2048,
141
+ maximumCacheDurationMs: epochTracker_1.defaultCacheExpiryTimeoutMs,
139
142
  };
140
143
  this.commitCache = new Map();
141
144
  this.attributesBlobHandles = new Set();
@@ -155,7 +158,7 @@ class OdspDocumentStorageService {
155
158
  this.snapshotUrl = this.odspResolvedUrl.endpoints.snapshotStorageUrl;
156
159
  this.attachmentPOSTUrl = this.odspResolvedUrl.endpoints.attachmentPOSTStorageUrl;
157
160
  this.attachmentGETUrl = this.odspResolvedUrl.endpoints.attachmentGETStorageUrl;
158
- this.odspSummaryUploadManager = new odspSummaryUploadManager_1.OdspSummaryUploadManager(this.snapshotUrl, getStorageToken, logger, epochTracker);
161
+ this.odspSummaryUploadManager = new odspSummaryUploadManager_1.OdspSummaryUploadManager(this.snapshotUrl, getStorageToken, logger, epochTracker, !!((_a = this.hostPolicy.sessionOptions) === null || _a === void 0 ? void 0 : _a.forceAccessTokenViaAuthorizationHeader));
159
162
  }
160
163
  set ops(ops) {
161
164
  common_utils_1.assert(this._ops === undefined, 0x0a5 /* "Trying to set ops when they are already set!" */);
@@ -173,8 +176,9 @@ class OdspDocumentStorageService {
173
176
  async createBlob(file) {
174
177
  this.checkAttachmentPOSTUrl();
175
178
  const response = await odspUtils_1.getWithRetryForTokenRefresh(async (options) => {
179
+ var _a;
176
180
  const storageToken = await this.getStorageToken(options, "CreateBlob");
177
- const { url, headers } = getUrlAndHeadersWithAuth_1.getUrlAndHeadersWithAuth(`${this.attachmentPOSTUrl}/content`, storageToken);
181
+ const { url, headers } = getUrlAndHeadersWithAuth_1.getUrlAndHeadersWithAuth(`${this.attachmentPOSTUrl}/content`, storageToken, !!((_a = this.hostPolicy.sessionOptions) === null || _a === void 0 ? void 0 : _a.forceAccessTokenViaAuthorizationHeader));
178
182
  headers["Content-Type"] = "application/octet-stream";
179
183
  return telemetry_utils_1.PerformanceEvent.timedExecAsync(this.logger, {
180
184
  eventName: "createBlob",
@@ -198,9 +202,10 @@ class OdspDocumentStorageService {
198
202
  if (blob === undefined) {
199
203
  this.checkAttachmentGETUrl();
200
204
  blob = await odspUtils_1.getWithRetryForTokenRefresh(async (options) => {
205
+ var _a;
201
206
  const storageToken = await this.getStorageToken(options, "GetBlob");
202
207
  const unAuthedUrl = `${this.attachmentGETUrl}/${encodeURIComponent(blobId)}/content`;
203
- const { url, headers } = getUrlAndHeadersWithAuth_1.getUrlAndHeadersWithAuth(unAuthedUrl, storageToken);
208
+ const { url, headers } = getUrlAndHeadersWithAuth_1.getUrlAndHeadersWithAuth(unAuthedUrl, storageToken, !!((_a = this.hostPolicy.sessionOptions) === null || _a === void 0 ? void 0 : _a.forceAccessTokenViaAuthorizationHeader));
204
209
  return telemetry_utils_1.PerformanceEvent.timedExecAsync(this.logger, {
205
210
  eventName: "readDataBlob",
206
211
  blobId,
@@ -376,8 +381,9 @@ class OdspDocumentStorageService {
376
381
  return id ? [{ id, treeId: undefined }] : [];
377
382
  }
378
383
  return odspUtils_1.getWithRetryForTokenRefresh(async (options) => {
384
+ var _a;
379
385
  const storageToken = await this.getStorageToken(options, "GetVersions");
380
- const { url, headers } = getUrlAndHeadersWithAuth_1.getUrlAndHeadersWithAuth(`${this.snapshotUrl}/versions?count=${count}`, storageToken);
386
+ const { url, headers } = getUrlAndHeadersWithAuth_1.getUrlAndHeadersWithAuth(`${this.snapshotUrl}/versions?count=${count}`, storageToken, !!((_a = this.hostPolicy.sessionOptions) === null || _a === void 0 ? void 0 : _a.forceAccessTokenViaAuthorizationHeader));
381
387
  // Fetch the latest snapshot versions for the document
382
388
  const response = await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.logger, {
383
389
  eventName: "getVersions",
@@ -422,6 +428,7 @@ class OdspDocumentStorageService {
422
428
  });
423
429
  }
424
430
  async fetchSnapshotCore(hostSnapshotOptions) {
431
+ var _a, _b;
425
432
  const snapshotOptions = Object.assign(Object.assign({ mds: this.maxSnapshotSizeLimit }, hostSnapshotOptions), { timeout: (hostSnapshotOptions === null || hostSnapshotOptions === void 0 ? void 0 : hostSnapshotOptions.timeout) ? Math.min(hostSnapshotOptions.timeout, this.maxSnapshotFetchTimeout) : this.maxSnapshotFetchTimeout });
426
433
  // No limit on size of snapshot or time to fetch, as otherwise we fail all clients to summarize
427
434
  if (this.hostPolicy.summarizerClient) {
@@ -438,7 +445,7 @@ class OdspDocumentStorageService {
438
445
  };
439
446
  const removeEntries = async () => this.cache.persistedCache.removeEntries();
440
447
  try {
441
- const odspSnapshot = await fetchSnapshot_1.fetchSnapshotWithRedeem(this.odspResolvedUrl, this.getStorageToken, snapshotOptions, this.logger, snapshotDownloader, putInCache, removeEntries, this.hostPolicy.enableRedeemFallback);
448
+ const odspSnapshot = await fetchSnapshot_1.fetchSnapshotWithRedeem(this.odspResolvedUrl, this.getStorageToken, snapshotOptions, !!((_a = this.hostPolicy.sessionOptions) === null || _a === void 0 ? void 0 : _a.forceAccessTokenViaAuthorizationHeader), this.logger, snapshotDownloader, putInCache, removeEntries, this.hostPolicy.enableRedeemFallback);
442
449
  return odspSnapshot;
443
450
  }
444
451
  catch (error) {
@@ -454,7 +461,7 @@ class OdspDocumentStorageService {
454
461
  errorType,
455
462
  });
456
463
  const snapshotOptionsWithoutBlobs = Object.assign(Object.assign({}, snapshotOptions), { blobs: 0, mds: undefined, timeout: undefined });
457
- const odspSnapshot = await fetchSnapshot_1.fetchSnapshotWithRedeem(this.odspResolvedUrl, this.getStorageToken, snapshotOptionsWithoutBlobs, this.logger, snapshotDownloader, putInCache, removeEntries, this.hostPolicy.enableRedeemFallback);
464
+ const odspSnapshot = await fetchSnapshot_1.fetchSnapshotWithRedeem(this.odspResolvedUrl, this.getStorageToken, snapshotOptionsWithoutBlobs, !!((_b = this.hostPolicy.sessionOptions) === null || _b === void 0 ? void 0 : _b.forceAccessTokenViaAuthorizationHeader), this.logger, snapshotDownloader, putInCache, removeEntries, this.hostPolicy.enableRedeemFallback);
458
465
  return odspSnapshot;
459
466
  }
460
467
  throw error;
@@ -519,12 +526,12 @@ class OdspDocumentStorageService {
519
526
  let tree = this.commitCache.get(id);
520
527
  if (!tree) {
521
528
  tree = await odspUtils_1.getWithRetryForTokenRefresh(async (options) => {
522
- var _a;
529
+ var _a, _b;
523
530
  const storageToken = await this.getStorageToken(options, "ReadCommit");
524
531
  const snapshotDownloader = async (url, fetchOptions) => {
525
532
  return this.epochTracker.fetchAndParseAsJSON(url, fetchOptions, "snapshotTree");
526
533
  };
527
- const snapshot = await fetchSnapshot_1.fetchSnapshot(this.snapshotUrl, storageToken, id, this.fetchFullSnapshot, this.logger, snapshotDownloader);
534
+ const snapshot = await fetchSnapshot_1.fetchSnapshot(this.snapshotUrl, storageToken, id, this.fetchFullSnapshot, !!((_a = this.hostPolicy.sessionOptions) === null || _a === void 0 ? void 0 : _a.forceAccessTokenViaAuthorizationHeader), this.logger, snapshotDownloader);
528
535
  let treeId = "";
529
536
  if (snapshot.snapshotTree) {
530
537
  common_utils_1.assert(snapshot.snapshotTree.id !== undefined, 0x222 /* "Root tree should contain the id!!" */);
@@ -536,7 +543,7 @@ class OdspDocumentStorageService {
536
543
  }
537
544
  // If the version id doesn't match with the id of the tree, then use the id of first tree which in that case
538
545
  // will be the actual id of tree to be fetched.
539
- return (_a = this.commitCache.get(id)) !== null && _a !== void 0 ? _a : this.commitCache.get(treeId);
546
+ return (_b = this.commitCache.get(id)) !== null && _b !== void 0 ? _b : this.commitCache.get(treeId);
540
547
  });
541
548
  }
542
549
  if (!tree) {
@@ -1 +1 @@
1
- {"version":3,"file":"odspDocumentStorageManager.js","sourceRoot":"","sources":["../src/odspDocumentStorageManager.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 { default as AbortController } from \"abort-controller\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport {\n assert,\n delay,\n} from \"@fluidframework/common-utils\";\nimport {\n PerformanceEvent,\n} from \"@fluidframework/telemetry-utils\";\nimport * as api from \"@fluidframework/protocol-definitions\";\nimport {\n ISummaryContext,\n IDocumentStorageService,\n LoaderCachingPolicy,\n DriverErrorType,\n} from \"@fluidframework/driver-definitions\";\nimport { RateLimiter, NonRetryableError } from \"@fluidframework/driver-utils\";\nimport {\n IOdspResolvedUrl,\n ISnapshotOptions,\n OdspErrorType,\n InstrumentedStorageTokenFetcher,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport {\n IDocumentStorageGetVersionsResponse,\n HostStoragePolicyInternal,\n IVersionedValueWithEpoch,\n ISnapshotCachedEntry,\n} from \"./contracts\";\nimport { downloadSnapshot, fetchSnapshot, fetchSnapshotWithRedeem } from \"./fetchSnapshot\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport { IOdspCache } from \"./odspCache\";\nimport {\n createCacheSnapshotKey,\n getWithRetryForTokenRefresh,\n ISnapshotContents,\n} from \"./odspUtils\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { OdspSummaryUploadManager } from \"./odspSummaryUploadManager\";\nimport { FlushResult } from \"./odspDocumentDeltaConnection\";\n\n/* eslint-disable max-len */\n\n// An implementation of Promise.race that gives you the winner of the promise race\nasync function promiseRaceWithWinner<T>(promises: Promise<T>[]): Promise<{ index: number, value: T }> {\n return new Promise((resolve, reject) => {\n promises.forEach((p, index) => {\n p.then((v) => resolve({ index, value: v })).catch(reject);\n });\n });\n}\n\nclass BlobCache {\n // Save the timeout so we can cancel and reschedule it as needed\n private blobCacheTimeout: ReturnType<typeof setTimeout> | undefined;\n // If the defer flag is set when the timeout fires, we'll reschedule rather than clear immediately\n // This deferral approach is used (rather than clearing/resetting the timer) as current calling patterns trigger\n // too many calls to setTimeout/clearTimeout.\n private deferBlobCacheClear: boolean = false;\n\n private readonly _blobCache: Map<string, ArrayBuffer> = new Map();\n\n // Tracks all blob IDs evicted from cache\n private readonly blobsEvicted: Set<string> = new Set();\n\n // Initial time-out to purge data from cache\n // If this time out is very small, then we purge blobs from cache too soon and that results in a lot of\n // requests to storage, which brings down perf and may trip protection limits causing 429s\n private blobCacheTimeoutDuration = 2 * 60 * 1000;\n\n // SPO does not keep old snapshots around for long, so we are running chances of not\n // being able to rehydrate data store / DDS in the future if we purge anything (and with blob de-duping,\n // even if blob read by runtime, it could be read again in the future)\n // So for now, purging is disabled.\n private readonly purgeEnabled = false;\n\n public get value() {\n return this._blobCache;\n }\n\n public addBlobs(blobs: Map<string, ArrayBuffer>) {\n blobs.forEach((value, blobId) => {\n this._blobCache.set(blobId, value);\n });\n // Reset the timer on cache set\n this.scheduleClearBlobsCache();\n }\n\n /**\n * Schedule a timer for clearing the blob cache or defer the current one.\n */\n private scheduleClearBlobsCache() {\n if (this.blobCacheTimeout !== undefined) {\n // If we already have an outstanding timer, just signal that we should defer the clear\n this.deferBlobCacheClear = true;\n } else if (this.purgeEnabled) {\n // If we don't have an outstanding timer, set a timer\n // When the timer runs out, we'll decide whether to proceed with the cache clear or reset the timer\n const clearCacheOrDefer = () => {\n this.blobCacheTimeout = undefined;\n if (this.deferBlobCacheClear) {\n this.deferBlobCacheClear = false;\n this.scheduleClearBlobsCache();\n } else {\n // NOTE: Slightly better algorithm here would be to purge either only big blobs,\n // or sort them by size and purge enough big blobs to leave only 256Kb of small blobs in cache\n // Purging is optimizing memory footprint. But count controls potential number of storage requests\n // We want to optimize both - memory footprint and number of future requests to storage.\n // Note that Container can realize data store or DDS on-demand at any point in time, so we do not\n // control when blobs will be used.\n this._blobCache.forEach((_, blobId) => this.blobsEvicted.add(blobId));\n this._blobCache.clear();\n }\n };\n this.blobCacheTimeout = setTimeout(clearCacheOrDefer, this.blobCacheTimeoutDuration);\n // any future storage reads that get into the cache should be cleared from cache rather quickly -\n // there is not much value in keeping them longer\n this.blobCacheTimeoutDuration = 10 * 1000;\n }\n }\n\n public getBlob(blobId: string) {\n // Reset the timer on attempted cache read\n this.scheduleClearBlobsCache();\n const blobContent = this._blobCache.get(blobId);\n const evicted = this.blobsEvicted.has(blobId);\n return { blobContent, evicted };\n }\n\n public setBlob(blobId: string, blob: ArrayBuffer) {\n // This API is called as result of cache miss and reading blob from storage.\n // Runtime never reads same blob twice.\n // The only reason we may get read request for same blob is blob de-duping in summaries.\n // Note that the bigger the size, the less likely blobs are the same, so there is very little benefit of caching big blobs.\n // Images are the only exception - user may insert same image twice. But we currently do not de-dup them - only snapshot\n // blobs are de-duped.\n const size = blob.byteLength;\n if (size < 256 * 1024) {\n // Reset the timer on cache set\n this.scheduleClearBlobsCache();\n return this._blobCache.set(blobId, blob);\n } else {\n // we evicted it here by not caching.\n this.blobsEvicted.add(blobId);\n }\n }\n}\n\nexport class OdspDocumentStorageService implements IDocumentStorageService {\n readonly policies = {\n // By default, ODSP tells the container not to prefetch/cache.\n caching: LoaderCachingPolicy.NoCaching,\n\n // ODSP storage works better if it has less number of blobs / edges\n // Runtime creating many small blobs results in sub-optimal perf.\n // 2K seems like the sweat spot:\n // The smaller the number, less blobs we aggregate. Most storages are very likely to have notion\n // of minimal \"cluster\" size, so having small blobs is wasteful\n // At the same time increasing the limit ensure that more blobs with user content are aggregated,\n // reducing possibility for de-duping of same blobs (i.e. .attributes rolled into aggregate blob\n // are not reused across data stores, or even within data store, resulting in duplication of content)\n // Note that duplication of content should not have significant impact for bytes over wire as\n // compression of http payload mostly takes care of it, but it does impact storage size and in-memory sizes.\n minBlobSize: 2048,\n };\n\n private readonly commitCache: Map<string, api.ISnapshotTree> = new Map();\n\n private readonly attributesBlobHandles: Set<string> = new Set();\n\n private readonly odspSummaryUploadManager: OdspSummaryUploadManager;\n private _ops: api.ISequencedDocumentMessage[] | undefined;\n\n private firstVersionCall = true;\n private _snapshotSequenceNumber: number | undefined;\n\n private readonly documentId: string;\n private readonly snapshotUrl: string | undefined;\n private readonly attachmentPOSTUrl: string | undefined;\n private readonly attachmentGETUrl: string | undefined;\n // Driver specified limits for snapshot size and time.\n /**\n * NOTE: While commit cfff6e3 added restrictions to prevent large payloads, snapshot failures will continue to\n * happen until blob request throttling is implemented. Until then, as a temporary fix we set arbitrarily large\n * snapshot size and timeout limits so that such failures are unlikely to occur.\n */\n private readonly maxSnapshotSizeLimit = 500000000; // 500 MB\n private readonly maxSnapshotFetchTimeout = 120000; // 2 min\n\n // limits the amount of parallel \"attachment\" blob uploads\n private readonly createBlobRateLimiter = new RateLimiter(1);\n\n private readonly blobCache = new BlobCache();\n\n public set ops(ops: api.ISequencedDocumentMessage[] | undefined) {\n assert(this._ops === undefined, 0x0a5 /* \"Trying to set ops when they are already set!\" */);\n this._ops = ops;\n }\n\n public get ops(): api.ISequencedDocumentMessage[] | undefined {\n return this._ops;\n }\n\n public get snapshotSequenceNumber() {\n return this._snapshotSequenceNumber;\n }\n\n constructor(\n private readonly odspResolvedUrl: IOdspResolvedUrl,\n private readonly getStorageToken: InstrumentedStorageTokenFetcher,\n private readonly logger: ITelemetryLogger,\n private readonly fetchFullSnapshot: boolean,\n private readonly cache: IOdspCache,\n private readonly hostPolicy: HostStoragePolicyInternal,\n private readonly epochTracker: EpochTracker,\n private readonly flushCallback: () => Promise<FlushResult>,\n ) {\n this.documentId = this.odspResolvedUrl.hashedDocumentId;\n this.snapshotUrl = this.odspResolvedUrl.endpoints.snapshotStorageUrl;\n this.attachmentPOSTUrl = this.odspResolvedUrl.endpoints.attachmentPOSTStorageUrl;\n this.attachmentGETUrl = this.odspResolvedUrl.endpoints.attachmentGETStorageUrl;\n this.odspSummaryUploadManager = new OdspSummaryUploadManager(this.snapshotUrl, getStorageToken, logger, epochTracker);\n }\n\n public get repositoryUrl(): string {\n return \"\";\n }\n\n public async createBlob(file: ArrayBufferLike): Promise<api.ICreateBlobResponse> {\n this.checkAttachmentPOSTUrl();\n\n const response = await getWithRetryForTokenRefresh(async (options) => {\n const storageToken = await this.getStorageToken(options, \"CreateBlob\");\n const { url, headers } = getUrlAndHeadersWithAuth(`${this.attachmentPOSTUrl}/content`, storageToken);\n headers[\"Content-Type\"] = \"application/octet-stream\";\n\n return PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"createBlob\",\n size: file.byteLength,\n waitQueueLength: this.createBlobRateLimiter.waitQueueLength,\n },\n async (event) => {\n const res = await this.createBlobRateLimiter.schedule(async () =>\n this.epochTracker.fetchAndParseAsJSON<api.ICreateBlobResponse>(\n url,\n {\n body: file,\n headers,\n method: \"POST\",\n },\n \"createBlob\",\n ));\n event.end({\n blobId: res.content.id,\n ...res.commonSpoHeaders,\n });\n return res;\n },\n );\n });\n\n return response.content;\n }\n\n private async readBlobCore(blobId: string): Promise<ArrayBuffer> {\n const { blobContent, evicted } = this.blobCache.getBlob(blobId);\n let blob = blobContent;\n\n if (blob === undefined) {\n this.checkAttachmentGETUrl();\n\n blob = await getWithRetryForTokenRefresh(async (options) => {\n const storageToken = await this.getStorageToken(options, \"GetBlob\");\n const unAuthedUrl = `${this.attachmentGETUrl}/${encodeURIComponent(blobId)}/content`;\n const { url, headers } = getUrlAndHeadersWithAuth(unAuthedUrl, storageToken);\n\n return PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"readDataBlob\",\n blobId,\n evicted,\n headers: Object.keys(headers).length !== 0 ? true : undefined,\n waitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,\n },\n async (event) => {\n const res = await this.epochTracker.fetchArray(url, { headers }, \"blob\");\n event.end({\n waitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,\n ...res.commonSpoHeaders,\n attempts: options.refresh ? 2 : 1,\n });\n const cacheControl = res.headers.get(\"cache-control\");\n if (cacheControl === undefined || !(cacheControl.includes(\"private\") || cacheControl.includes(\"public\"))) {\n this.logger.sendErrorEvent({\n eventName: \"NonCacheableBlob\",\n cacheControl,\n blobId,\n ...res.commonSpoHeaders,\n });\n }\n return res.content;\n },\n );\n });\n this.blobCache.setBlob(blobId, blob);\n }\n\n return blob;\n }\n\n public async readBlob(blobId: string): Promise<ArrayBufferLike> {\n return this.readBlobCore(blobId);\n }\n\n public async getSnapshotTree(version?: api.IVersion): Promise<api.ISnapshotTree | null> {\n if (!this.snapshotUrl) {\n return null;\n }\n\n let id: string;\n if (!version || !version.id) {\n const versions = await this.getVersions(null, 1);\n if (!versions || versions.length === 0) {\n return null;\n }\n id = versions[0].id;\n } else {\n id = version.id;\n }\n\n const snapshotTree = await this.readTree(id);\n if (!snapshotTree) {\n return null;\n }\n // Decode commit paths\n const commits = {};\n\n for (const key of Object.keys(snapshotTree.commits)) {\n commits[decodeURIComponent(key)] = snapshotTree.commits[key];\n }\n\n let finalTree: api.ISnapshotTree;\n // For container loaded from detach new summary, we will not have a commit for \".app\" in downloaded summary as the client uploaded both\n // \".app\" and \".protocol\" trees by itself. For other summaries, we will have \".app\" as commit because client previously only uploaded the\n // app summary.\n if (commits && commits[\".app\"]) {\n // The latest snapshot is a summary\n // attempt to read .protocol from commits for backwards compat\n finalTree = await this.readSummaryTree(commits[\".protocol\"] || snapshotTree.trees[\".protocol\"], commits[\".app\"] as string);\n } else {\n if (snapshotTree.blobs) {\n const attributesBlob = snapshotTree.blobs.attributes;\n if (attributesBlob) {\n this.attributesBlobHandles.add(attributesBlob);\n }\n }\n\n snapshotTree.commits = commits;\n\n // When we upload the container snapshot, we upload appTree in \".app\" and protocol tree in \".protocol\"\n // So when we request the snapshot we get \".app\" as tree and not as commit node as in the case just above.\n const appTree = snapshotTree.trees[\".app\"];\n const protocolTree = snapshotTree.trees[\".protocol\"];\n finalTree = this.combineProtocolAndAppSnapshotTree(appTree, protocolTree);\n }\n return finalTree;\n }\n\n public async getVersions(blobid: string | null, count: number): Promise<api.IVersion[]> {\n // Regular load workflow uses blobId === documentID to indicate \"latest\".\n if (blobid !== this.documentId && blobid) {\n // FluidFetch & FluidDebugger tools use empty sting to query for versions\n // In such case we need to make a call against SPO to give full picture to the tool.\n // Otherwise, each commit calls getVersions but odsp doesn't have a history for each commit\n // return the blobid as is\n return [\n {\n id: blobid,\n treeId: undefined!,\n },\n ];\n }\n\n // Can't really make a call if we do not have URL\n if (!this.snapshotUrl) {\n return [];\n }\n\n // If count is one, we can use the trees/latest API, which returns the latest version and trees in a single request for better performance\n // Do it only once - we might get more here due to summarizer - it needs only container tree, not full snapshot.\n if (this.firstVersionCall && count === 1 && (blobid === null || blobid === this.documentId)) {\n const hostSnapshotOptions = this.hostPolicy.snapshotOptions;\n const odspSnapshotCacheValue: ISnapshotContents = await PerformanceEvent.timedExecAsync(\n this.logger,\n { eventName: \"ObtainSnapshot\" },\n async (event: PerformanceEvent) => {\n const props = {};\n let retrievedSnapshot: ISnapshotContents | undefined;\n // Here's the logic to grab the persistent cache snapshot implemented by the host\n // Epoch tracker is responsible for communicating with the persistent cache, handling epochs and cache versions\n const cachedSnapshotP: Promise<ISnapshotContents | undefined> =\n this.epochTracker.get(createCacheSnapshotKey(this.odspResolvedUrl))\n .then(async (snapshotCachedEntry: ISnapshotCachedEntry) => {\n if (snapshotCachedEntry !== undefined) {\n // If the cached entry does not contain the entry time, then assign it a default of 30 days old.\n const age = Date.now() - (snapshotCachedEntry.cacheEntryTime ??\n (Date.now() - 30 * 24 * 60 * 60 * 1000));\n\n // Record the cache age\n // eslint-disable-next-line @typescript-eslint/dot-notation\n props[\"cacheEntryAge\"] = age;\n }\n\n return snapshotCachedEntry;\n });\n\n // Based on the concurrentSnapshotFetch policy:\n // Either retrieve both the network and cache snapshots concurrently and pick the first to return,\n // or grab the cache value and then the network value if the cache value returns undefined.\n let method: string;\n if (this.hostPolicy.concurrentSnapshotFetch && !this.hostPolicy.summarizerClient) {\n const networkSnapshotP = this.fetchSnapshot(hostSnapshotOptions);\n\n // Ensure that failures on both paths are ignored initially.\n // I.e. if cache fails for some reason, we will proceed with network result.\n // And vice versa - if (for example) client is offline and network request fails first, we\n // do want to attempt to succeed with cached data!\n const promiseRaceWinner = await promiseRaceWithWinner([\n cachedSnapshotP.catch(() => undefined),\n networkSnapshotP.catch(() => undefined),\n ]);\n retrievedSnapshot = promiseRaceWinner.value;\n method = promiseRaceWinner.index === 0 ? \"cache\" : \"network\";\n\n if (retrievedSnapshot === undefined) {\n // if network failed -> wait for cache ( then return network failure)\n // If cache returned empty or failed -> wait for network (success of failure)\n if (promiseRaceWinner.index === 1) {\n retrievedSnapshot = await cachedSnapshotP;\n method = \"cache\";\n }\n if (retrievedSnapshot === undefined) {\n retrievedSnapshot = await networkSnapshotP;\n method = \"network\";\n }\n }\n } else {\n // Note: There's a race condition here - another caller may come past the undefined check\n // while the first caller is awaiting later async code in this block.\n\n retrievedSnapshot = await cachedSnapshotP;\n\n method = retrievedSnapshot !== undefined ? \"cache\" : \"network\";\n\n if (retrievedSnapshot === undefined) {\n retrievedSnapshot = await this.fetchSnapshot(hostSnapshotOptions);\n }\n }\n if (method === \"network\") {\n // eslint-disable-next-line @typescript-eslint/dot-notation\n props[\"cacheEntryAge\"] = undefined;\n }\n event.end({ ...props, method });\n return retrievedSnapshot;\n },\n );\n\n // Successful call, make network calls only\n this.firstVersionCall = false;\n\n this._snapshotSequenceNumber = odspSnapshotCacheValue.sequenceNumber;\n const { snapshotTree, blobs, ops } = odspSnapshotCacheValue;\n // id should be undefined in case of just ops in snapshot.\n let id: string | undefined;\n if (snapshotTree) {\n id = snapshotTree.id;\n assert(id !== undefined, 0x221 /* \"Root tree should contain the id\" */);\n this.setRootTree(id, snapshotTree);\n }\n if (blobs) {\n this.initBlobsCache(blobs);\n }\n\n this.ops = ops;\n return id ? [{ id, treeId: undefined! }] : [];\n }\n\n return getWithRetryForTokenRefresh(async (options) => {\n const storageToken = await this.getStorageToken(options, \"GetVersions\");\n const { url, headers } = getUrlAndHeadersWithAuth(`${this.snapshotUrl}/versions?count=${count}`, storageToken);\n\n // Fetch the latest snapshot versions for the document\n const response = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"getVersions\",\n headers: Object.keys(headers).length !== 0 ? true : undefined,\n },\n async () => this.epochTracker.fetchAndParseAsJSON<IDocumentStorageGetVersionsResponse>(url, { headers }, \"versions\"),\n );\n const versionsResponse = response.content;\n if (!versionsResponse) {\n throw new NonRetryableError(\n \"getVersionsReturnedNoResponse\",\n \"No response from /versions endpoint\",\n DriverErrorType.genericNetworkError);\n }\n if (!Array.isArray(versionsResponse.value)) {\n throw new NonRetryableError(\n \"getVersionsReturnedNonArrayResponse\",\n \"Incorrect response from /versions endpoint\",\n DriverErrorType.genericNetworkError);\n }\n return versionsResponse.value.map((version) => {\n // Parse the date from the message\n let date: string | undefined;\n for (const rec of version.message.split(\"\\n\")) {\n const index = rec.indexOf(\":\");\n if (index !== -1 && rec.substr(0, index) === \"Date\") {\n date = rec.substr(index + 1).trim();\n break;\n }\n }\n return {\n date,\n id: version.id,\n treeId: undefined!,\n };\n });\n });\n }\n\n private async fetchSnapshot(hostSnapshotOptions: ISnapshotOptions | undefined) {\n return this.fetchSnapshotCore(hostSnapshotOptions).catch((error) => {\n // Issue #5895:\n // If we are offline, this error is retryable. But that means that RetriableDocumentStorageService\n // will run in circles calling getSnapshotTree, which would result in OdspDocumentStorageService class\n // going getVersions / individual blob download path. This path is very slow, and will not work with\n // delay-loaded data stores and ODSP storage deleting old snapshots and blobs.\n if (typeof error === \"object\" && error !== null) {\n error.canRetry = false;\n }\n throw error;\n });\n }\n\n private async fetchSnapshotCore(hostSnapshotOptions: ISnapshotOptions | undefined) {\n const snapshotOptions: ISnapshotOptions = {\n mds: this.maxSnapshotSizeLimit,\n ...hostSnapshotOptions,\n timeout: hostSnapshotOptions?.timeout ? Math.min(hostSnapshotOptions.timeout, this.maxSnapshotFetchTimeout) : this.maxSnapshotFetchTimeout,\n };\n\n // No limit on size of snapshot or time to fetch, as otherwise we fail all clients to summarize\n if (this.hostPolicy.summarizerClient) {\n snapshotOptions.mds = undefined;\n snapshotOptions.timeout = undefined;\n }\n\n const snapshotDownloader = async (\n finalOdspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n options: ISnapshotOptions | undefined,\n controller?: AbortController,\n ) => {\n return downloadSnapshot(\n finalOdspResolvedUrl,\n storageToken,\n this.logger,\n options,\n this.hostPolicy.fetchBinarySnapshotFormat,\n controller,\n this.epochTracker,\n );\n };\n const putInCache = async (valueWithEpoch: IVersionedValueWithEpoch) => {\n return this.cache.persistedCache.put(\n createCacheSnapshotKey(this.odspResolvedUrl),\n // Epoch tracker will add the epoch and version to the value here. So just send value to cache.\n valueWithEpoch.value,\n );\n };\n const removeEntries = async () => this.cache.persistedCache.removeEntries();\n try {\n const odspSnapshot = await fetchSnapshotWithRedeem(\n this.odspResolvedUrl,\n this.getStorageToken,\n snapshotOptions,\n this.logger,\n snapshotDownloader,\n putInCache,\n removeEntries,\n this.hostPolicy.enableRedeemFallback);\n return odspSnapshot;\n } catch (error) {\n const errorType = error.errorType;\n // If the snapshot size is too big and the host specified the size limitation(specified in hostSnapshotOptions), then don't try to fetch the snapshot again.\n if ((errorType === OdspErrorType.snapshotTooBig && hostSnapshotOptions?.mds !== undefined) && (this.hostPolicy.summarizerClient !== true)) {\n throw error;\n }\n // If the first snapshot request was with blobs and we either timed out or the size was too big, then try to fetch without blobs.\n if ((errorType === OdspErrorType.snapshotTooBig || errorType === OdspErrorType.fetchTimeout) && snapshotOptions.blobs) {\n this.logger.sendErrorEvent({\n eventName: \"TreeLatest_SecondCall\",\n errorType,\n });\n const snapshotOptionsWithoutBlobs: ISnapshotOptions = { ...snapshotOptions, blobs: 0, mds: undefined, timeout: undefined };\n const odspSnapshot = await fetchSnapshotWithRedeem(\n this.odspResolvedUrl,\n this.getStorageToken,\n snapshotOptionsWithoutBlobs,\n this.logger,\n snapshotDownloader,\n putInCache,\n removeEntries,\n this.hostPolicy.enableRedeemFallback);\n return odspSnapshot;\n }\n throw error;\n }\n }\n\n public async write(tree: api.ITree, parents: string[], message: string): Promise<api.IVersion> {\n this.checkSnapshotUrl();\n\n throw new Error(\"Not supported\");\n }\n\n public async uploadSummaryWithContext(summary: api.ISummaryTree, context: ISummaryContext): Promise<string> {\n this.checkSnapshotUrl();\n\n // Enable flushing only if we have single commit summary and this is not the initial summary for an empty file\n if (\".protocol\" in summary.tree && context.ackHandle !== undefined) {\n let retry = 0;\n for (;;) {\n const result = await this.flushCallback();\n const seq = result.lastPersistedSequenceNumber;\n if (seq !== undefined && seq >= context.referenceSequenceNumber) {\n break;\n }\n\n retry++;\n if (retry > 3) {\n this.logger.sendErrorEvent({\n eventName: \"FlushFailure\",\n ...result,\n retry,\n referenceSequenceNumber: context.referenceSequenceNumber,\n });\n break;\n }\n\n this.logger.sendPerformanceEvent({\n eventName: \"FlushExtraCall\",\n ...result,\n retry,\n referenceSequenceNumber: context.referenceSequenceNumber,\n });\n\n await delay(1000 * (result.retryAfter ?? 1));\n }\n }\n\n const id = await PerformanceEvent.timedExecAsync(this.logger,\n { eventName: \"uploadSummaryWithContext\" },\n async () => this.odspSummaryUploadManager.writeSummaryTree(summary, context));\n return id;\n }\n\n public async downloadSummary(commit: api.ISummaryHandle): Promise<api.ISummaryTree> {\n throw new Error(\"Not implemented yet\");\n }\n\n private setRootTree(id: string, tree: api.ISnapshotTree) {\n this.commitCache.set(id, tree);\n }\n\n private initBlobsCache(blobs: Map<string, ArrayBuffer>) {\n this.blobCache.addBlobs(blobs);\n }\n\n private checkSnapshotUrl() {\n if (!this.snapshotUrl) {\n throw new NonRetryableError(\n \"noSnapshotUrlProvided\",\n \"Method failed because no snapshot url was available\",\n DriverErrorType.genericError);\n }\n }\n\n private checkAttachmentPOSTUrl() {\n if (!this.attachmentPOSTUrl) {\n throw new NonRetryableError(\n \"noAttachmentPOSTUrlProvided\",\n \"Method failed because no attachment POST url was available\",\n DriverErrorType.genericError);\n }\n }\n\n private checkAttachmentGETUrl() {\n if (!this.attachmentGETUrl) {\n throw new NonRetryableError(\n \"noAttachmentGETUrlWasProvided\",\n \"Method failed because no attachment GET url was available\",\n DriverErrorType.genericError);\n }\n }\n\n private async readTree(id: string): Promise<api.ISnapshotTree | null> {\n if (!this.snapshotUrl) {\n return null;\n }\n let tree = this.commitCache.get(id);\n if (!tree) {\n tree = await getWithRetryForTokenRefresh(async (options) => {\n const storageToken = await this.getStorageToken(options, \"ReadCommit\");\n const snapshotDownloader = async (url: string, fetchOptions: {[index: string]: any}) => {\n return this.epochTracker.fetchAndParseAsJSON(\n url,\n fetchOptions,\n \"snapshotTree\",\n );\n };\n const snapshot = await fetchSnapshot(this.snapshotUrl!, storageToken, id, this.fetchFullSnapshot, this.logger, snapshotDownloader);\n let treeId = \"\";\n if (snapshot.snapshotTree) {\n assert(snapshot.snapshotTree.id !== undefined, 0x222 /* \"Root tree should contain the id!!\" */);\n treeId = snapshot.snapshotTree.id;\n this.setRootTree(treeId, snapshot.snapshotTree);\n }\n if (snapshot.blobs) {\n this.initBlobsCache(snapshot.blobs);\n }\n // If the version id doesn't match with the id of the tree, then use the id of first tree which in that case\n // will be the actual id of tree to be fetched.\n return this.commitCache.get(id) ?? this.commitCache.get(treeId);\n });\n }\n\n if (!tree) {\n return null;\n }\n\n return tree;\n }\n\n /**\n * Reads a summary tree\n * @param protocolTreeOrId - Protocol snapshot tree or id of the protocol tree\n * @param appTreeId - Id of the app tree\n */\n private async readSummaryTree(protocolTreeOrId: api.ISnapshotTree | string, appTreeId: string): Promise<api.ISnapshotTree> {\n // Load the app and protocol trees and return them\n let hierarchicalProtocolTree: api.ISnapshotTree | null;\n if (typeof (protocolTreeOrId) === \"string\") {\n // Backwards compat for older summaries\n hierarchicalProtocolTree = await this.readTree(protocolTreeOrId);\n } else {\n hierarchicalProtocolTree = protocolTreeOrId;\n }\n\n const hierarchicalAppTree = await this.readTree(appTreeId);\n if (!hierarchicalProtocolTree) {\n throw new Error(\"Invalid protocol tree\");\n }\n\n if (!hierarchicalAppTree) {\n throw new Error(\"Invalid app tree\");\n }\n\n if (hierarchicalProtocolTree.blobs) {\n const attributesBlob = hierarchicalProtocolTree.blobs.attributes;\n if (attributesBlob) {\n this.attributesBlobHandles.add(attributesBlob);\n }\n }\n return this.combineProtocolAndAppSnapshotTree(hierarchicalAppTree, hierarchicalProtocolTree);\n }\n\n private combineProtocolAndAppSnapshotTree(\n hierarchicalAppTree: api.ISnapshotTree,\n hierarchicalProtocolTree: api.ISnapshotTree,\n ) {\n const summarySnapshotTree: api.ISnapshotTree = {\n blobs: {\n ...hierarchicalAppTree.blobs,\n },\n commits: {\n ...hierarchicalAppTree.commits,\n },\n trees: {\n ...hierarchicalAppTree.trees,\n // the app tree could have a .protocol\n // in that case we want to server protocol to override it\n \".protocol\": hierarchicalProtocolTree,\n },\n };\n\n return summarySnapshotTree;\n }\n}\n\n/* eslint-enable max-len */\n"]}
1
+ {"version":3,"file":"odspDocumentStorageManager.js","sourceRoot":"","sources":["../src/odspDocumentStorageManager.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 { default as AbortController } from \"abort-controller\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport {\n assert,\n delay,\n} from \"@fluidframework/common-utils\";\nimport {\n PerformanceEvent,\n} from \"@fluidframework/telemetry-utils\";\nimport * as api from \"@fluidframework/protocol-definitions\";\nimport {\n ISummaryContext,\n IDocumentStorageService,\n LoaderCachingPolicy,\n DriverErrorType,\n} from \"@fluidframework/driver-definitions\";\nimport { RateLimiter, NonRetryableError } from \"@fluidframework/driver-utils\";\nimport {\n IOdspResolvedUrl,\n ISnapshotOptions,\n OdspErrorType,\n InstrumentedStorageTokenFetcher,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport {\n IDocumentStorageGetVersionsResponse,\n HostStoragePolicyInternal,\n IVersionedValueWithEpoch,\n ISnapshotCachedEntry,\n} from \"./contracts\";\nimport { downloadSnapshot, fetchSnapshot, fetchSnapshotWithRedeem } from \"./fetchSnapshot\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport { IOdspCache } from \"./odspCache\";\nimport {\n createCacheSnapshotKey,\n getWithRetryForTokenRefresh,\n ISnapshotContents,\n} from \"./odspUtils\";\nimport { defaultCacheExpiryTimeoutMs, EpochTracker } from \"./epochTracker\";\nimport { OdspSummaryUploadManager } from \"./odspSummaryUploadManager\";\nimport { FlushResult } from \"./odspDocumentDeltaConnection\";\n\n/* eslint-disable max-len */\n\n// An implementation of Promise.race that gives you the winner of the promise race\nasync function promiseRaceWithWinner<T>(promises: Promise<T>[]): Promise<{ index: number, value: T }> {\n return new Promise((resolve, reject) => {\n promises.forEach((p, index) => {\n p.then((v) => resolve({ index, value: v })).catch(reject);\n });\n });\n}\n\nclass BlobCache {\n // Save the timeout so we can cancel and reschedule it as needed\n private blobCacheTimeout: ReturnType<typeof setTimeout> | undefined;\n // If the defer flag is set when the timeout fires, we'll reschedule rather than clear immediately\n // This deferral approach is used (rather than clearing/resetting the timer) as current calling patterns trigger\n // too many calls to setTimeout/clearTimeout.\n private deferBlobCacheClear: boolean = false;\n\n private readonly _blobCache: Map<string, ArrayBuffer> = new Map();\n\n // Tracks all blob IDs evicted from cache\n private readonly blobsEvicted: Set<string> = new Set();\n\n // Initial time-out to purge data from cache\n // If this time out is very small, then we purge blobs from cache too soon and that results in a lot of\n // requests to storage, which brings down perf and may trip protection limits causing 429s\n private blobCacheTimeoutDuration = 2 * 60 * 1000;\n\n // SPO does not keep old snapshots around for long, so we are running chances of not\n // being able to rehydrate data store / DDS in the future if we purge anything (and with blob de-duping,\n // even if blob read by runtime, it could be read again in the future)\n // So for now, purging is disabled.\n private readonly purgeEnabled = false;\n\n public get value() {\n return this._blobCache;\n }\n\n public addBlobs(blobs: Map<string, ArrayBuffer>) {\n blobs.forEach((value, blobId) => {\n this._blobCache.set(blobId, value);\n });\n // Reset the timer on cache set\n this.scheduleClearBlobsCache();\n }\n\n /**\n * Schedule a timer for clearing the blob cache or defer the current one.\n */\n private scheduleClearBlobsCache() {\n if (this.blobCacheTimeout !== undefined) {\n // If we already have an outstanding timer, just signal that we should defer the clear\n this.deferBlobCacheClear = true;\n } else if (this.purgeEnabled) {\n // If we don't have an outstanding timer, set a timer\n // When the timer runs out, we'll decide whether to proceed with the cache clear or reset the timer\n const clearCacheOrDefer = () => {\n this.blobCacheTimeout = undefined;\n if (this.deferBlobCacheClear) {\n this.deferBlobCacheClear = false;\n this.scheduleClearBlobsCache();\n } else {\n // NOTE: Slightly better algorithm here would be to purge either only big blobs,\n // or sort them by size and purge enough big blobs to leave only 256Kb of small blobs in cache\n // Purging is optimizing memory footprint. But count controls potential number of storage requests\n // We want to optimize both - memory footprint and number of future requests to storage.\n // Note that Container can realize data store or DDS on-demand at any point in time, so we do not\n // control when blobs will be used.\n this._blobCache.forEach((_, blobId) => this.blobsEvicted.add(blobId));\n this._blobCache.clear();\n }\n };\n this.blobCacheTimeout = setTimeout(clearCacheOrDefer, this.blobCacheTimeoutDuration);\n // any future storage reads that get into the cache should be cleared from cache rather quickly -\n // there is not much value in keeping them longer\n this.blobCacheTimeoutDuration = 10 * 1000;\n }\n }\n\n public getBlob(blobId: string) {\n // Reset the timer on attempted cache read\n this.scheduleClearBlobsCache();\n const blobContent = this._blobCache.get(blobId);\n const evicted = this.blobsEvicted.has(blobId);\n return { blobContent, evicted };\n }\n\n public setBlob(blobId: string, blob: ArrayBuffer) {\n // This API is called as result of cache miss and reading blob from storage.\n // Runtime never reads same blob twice.\n // The only reason we may get read request for same blob is blob de-duping in summaries.\n // Note that the bigger the size, the less likely blobs are the same, so there is very little benefit of caching big blobs.\n // Images are the only exception - user may insert same image twice. But we currently do not de-dup them - only snapshot\n // blobs are de-duped.\n const size = blob.byteLength;\n if (size < 256 * 1024) {\n // Reset the timer on cache set\n this.scheduleClearBlobsCache();\n return this._blobCache.set(blobId, blob);\n } else {\n // we evicted it here by not caching.\n this.blobsEvicted.add(blobId);\n }\n }\n}\n\nexport class OdspDocumentStorageService implements IDocumentStorageService {\n readonly policies = {\n // By default, ODSP tells the container not to prefetch/cache.\n caching: LoaderCachingPolicy.NoCaching,\n\n // ODSP storage works better if it has less number of blobs / edges\n // Runtime creating many small blobs results in sub-optimal perf.\n // 2K seems like the sweat spot:\n // The smaller the number, less blobs we aggregate. Most storages are very likely to have notion\n // of minimal \"cluster\" size, so having small blobs is wasteful\n // At the same time increasing the limit ensure that more blobs with user content are aggregated,\n // reducing possibility for de-duping of same blobs (i.e. .attributes rolled into aggregate blob\n // are not reused across data stores, or even within data store, resulting in duplication of content)\n // Note that duplication of content should not have significant impact for bytes over wire as\n // compression of http payload mostly takes care of it, but it does impact storage size and in-memory sizes.\n minBlobSize: 2048,\n maximumCacheDurationMs: defaultCacheExpiryTimeoutMs,\n };\n\n private readonly commitCache: Map<string, api.ISnapshotTree> = new Map();\n\n private readonly attributesBlobHandles: Set<string> = new Set();\n\n private readonly odspSummaryUploadManager: OdspSummaryUploadManager;\n private _ops: api.ISequencedDocumentMessage[] | undefined;\n\n private firstVersionCall = true;\n private _snapshotSequenceNumber: number | undefined;\n\n private readonly documentId: string;\n private readonly snapshotUrl: string | undefined;\n private readonly attachmentPOSTUrl: string | undefined;\n private readonly attachmentGETUrl: string | undefined;\n // Driver specified limits for snapshot size and time.\n /**\n * NOTE: While commit cfff6e3 added restrictions to prevent large payloads, snapshot failures will continue to\n * happen until blob request throttling is implemented. Until then, as a temporary fix we set arbitrarily large\n * snapshot size and timeout limits so that such failures are unlikely to occur.\n */\n private readonly maxSnapshotSizeLimit = 500000000; // 500 MB\n private readonly maxSnapshotFetchTimeout = 120000; // 2 min\n\n // limits the amount of parallel \"attachment\" blob uploads\n private readonly createBlobRateLimiter = new RateLimiter(1);\n\n private readonly blobCache = new BlobCache();\n\n public set ops(ops: api.ISequencedDocumentMessage[] | undefined) {\n assert(this._ops === undefined, 0x0a5 /* \"Trying to set ops when they are already set!\" */);\n this._ops = ops;\n }\n\n public get ops(): api.ISequencedDocumentMessage[] | undefined {\n return this._ops;\n }\n\n public get snapshotSequenceNumber() {\n return this._snapshotSequenceNumber;\n }\n\n constructor(\n private readonly odspResolvedUrl: IOdspResolvedUrl,\n private readonly getStorageToken: InstrumentedStorageTokenFetcher,\n private readonly logger: ITelemetryLogger,\n private readonly fetchFullSnapshot: boolean,\n private readonly cache: IOdspCache,\n private readonly hostPolicy: HostStoragePolicyInternal,\n private readonly epochTracker: EpochTracker,\n private readonly flushCallback: () => Promise<FlushResult>,\n ) {\n this.documentId = this.odspResolvedUrl.hashedDocumentId;\n this.snapshotUrl = this.odspResolvedUrl.endpoints.snapshotStorageUrl;\n this.attachmentPOSTUrl = this.odspResolvedUrl.endpoints.attachmentPOSTStorageUrl;\n this.attachmentGETUrl = this.odspResolvedUrl.endpoints.attachmentGETStorageUrl;\n this.odspSummaryUploadManager = new OdspSummaryUploadManager(\n this.snapshotUrl,\n getStorageToken,\n logger,\n epochTracker,\n !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n );\n }\n\n public get repositoryUrl(): string {\n return \"\";\n }\n\n public async createBlob(file: ArrayBufferLike): Promise<api.ICreateBlobResponse> {\n this.checkAttachmentPOSTUrl();\n\n const response = await getWithRetryForTokenRefresh(async (options) => {\n const storageToken = await this.getStorageToken(options, \"CreateBlob\");\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${this.attachmentPOSTUrl}/content`,\n storageToken,\n !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n );\n headers[\"Content-Type\"] = \"application/octet-stream\";\n\n return PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"createBlob\",\n size: file.byteLength,\n waitQueueLength: this.createBlobRateLimiter.waitQueueLength,\n },\n async (event) => {\n const res = await this.createBlobRateLimiter.schedule(async () =>\n this.epochTracker.fetchAndParseAsJSON<api.ICreateBlobResponse>(\n url,\n {\n body: file,\n headers,\n method: \"POST\",\n },\n \"createBlob\",\n ));\n event.end({\n blobId: res.content.id,\n ...res.commonSpoHeaders,\n });\n return res;\n },\n );\n });\n\n return response.content;\n }\n\n private async readBlobCore(blobId: string): Promise<ArrayBuffer> {\n const { blobContent, evicted } = this.blobCache.getBlob(blobId);\n let blob = blobContent;\n\n if (blob === undefined) {\n this.checkAttachmentGETUrl();\n\n blob = await getWithRetryForTokenRefresh(async (options) => {\n const storageToken = await this.getStorageToken(options, \"GetBlob\");\n const unAuthedUrl = `${this.attachmentGETUrl}/${encodeURIComponent(blobId)}/content`;\n const { url, headers } = getUrlAndHeadersWithAuth(\n unAuthedUrl,\n storageToken,\n !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n );\n\n return PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"readDataBlob\",\n blobId,\n evicted,\n headers: Object.keys(headers).length !== 0 ? true : undefined,\n waitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,\n },\n async (event) => {\n const res = await this.epochTracker.fetchArray(url, { headers }, \"blob\");\n event.end({\n waitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,\n ...res.commonSpoHeaders,\n attempts: options.refresh ? 2 : 1,\n });\n const cacheControl = res.headers.get(\"cache-control\");\n if (cacheControl === undefined || !(cacheControl.includes(\"private\") || cacheControl.includes(\"public\"))) {\n this.logger.sendErrorEvent({\n eventName: \"NonCacheableBlob\",\n cacheControl,\n blobId,\n ...res.commonSpoHeaders,\n });\n }\n return res.content;\n },\n );\n });\n this.blobCache.setBlob(blobId, blob);\n }\n\n return blob;\n }\n\n public async readBlob(blobId: string): Promise<ArrayBufferLike> {\n return this.readBlobCore(blobId);\n }\n\n public async getSnapshotTree(version?: api.IVersion): Promise<api.ISnapshotTree | null> {\n if (!this.snapshotUrl) {\n return null;\n }\n\n let id: string;\n if (!version || !version.id) {\n const versions = await this.getVersions(null, 1);\n if (!versions || versions.length === 0) {\n return null;\n }\n id = versions[0].id;\n } else {\n id = version.id;\n }\n\n const snapshotTree = await this.readTree(id);\n if (!snapshotTree) {\n return null;\n }\n // Decode commit paths\n const commits = {};\n\n for (const key of Object.keys(snapshotTree.commits)) {\n commits[decodeURIComponent(key)] = snapshotTree.commits[key];\n }\n\n let finalTree: api.ISnapshotTree;\n // For container loaded from detach new summary, we will not have a commit for \".app\" in downloaded summary as the client uploaded both\n // \".app\" and \".protocol\" trees by itself. For other summaries, we will have \".app\" as commit because client previously only uploaded the\n // app summary.\n if (commits && commits[\".app\"]) {\n // The latest snapshot is a summary\n // attempt to read .protocol from commits for backwards compat\n finalTree = await this.readSummaryTree(commits[\".protocol\"] || snapshotTree.trees[\".protocol\"], commits[\".app\"] as string);\n } else {\n if (snapshotTree.blobs) {\n const attributesBlob = snapshotTree.blobs.attributes;\n if (attributesBlob) {\n this.attributesBlobHandles.add(attributesBlob);\n }\n }\n\n snapshotTree.commits = commits;\n\n // When we upload the container snapshot, we upload appTree in \".app\" and protocol tree in \".protocol\"\n // So when we request the snapshot we get \".app\" as tree and not as commit node as in the case just above.\n const appTree = snapshotTree.trees[\".app\"];\n const protocolTree = snapshotTree.trees[\".protocol\"];\n finalTree = this.combineProtocolAndAppSnapshotTree(appTree, protocolTree);\n }\n return finalTree;\n }\n\n public async getVersions(blobid: string | null, count: number): Promise<api.IVersion[]> {\n // Regular load workflow uses blobId === documentID to indicate \"latest\".\n if (blobid !== this.documentId && blobid) {\n // FluidFetch & FluidDebugger tools use empty sting to query for versions\n // In such case we need to make a call against SPO to give full picture to the tool.\n // Otherwise, each commit calls getVersions but odsp doesn't have a history for each commit\n // return the blobid as is\n return [\n {\n id: blobid,\n treeId: undefined!,\n },\n ];\n }\n\n // Can't really make a call if we do not have URL\n if (!this.snapshotUrl) {\n return [];\n }\n\n // If count is one, we can use the trees/latest API, which returns the latest version and trees in a single request for better performance\n // Do it only once - we might get more here due to summarizer - it needs only container tree, not full snapshot.\n if (this.firstVersionCall && count === 1 && (blobid === null || blobid === this.documentId)) {\n const hostSnapshotOptions = this.hostPolicy.snapshotOptions;\n const odspSnapshotCacheValue: ISnapshotContents = await PerformanceEvent.timedExecAsync(\n this.logger,\n { eventName: \"ObtainSnapshot\" },\n async (event: PerformanceEvent) => {\n const props = {};\n let retrievedSnapshot: ISnapshotContents | undefined;\n // Here's the logic to grab the persistent cache snapshot implemented by the host\n // Epoch tracker is responsible for communicating with the persistent cache, handling epochs and cache versions\n const cachedSnapshotP: Promise<ISnapshotContents | undefined> =\n this.epochTracker.get(createCacheSnapshotKey(this.odspResolvedUrl))\n .then(async (snapshotCachedEntry: ISnapshotCachedEntry) => {\n if (snapshotCachedEntry !== undefined) {\n // If the cached entry does not contain the entry time, then assign it a default of 30 days old.\n const age = Date.now() - (snapshotCachedEntry.cacheEntryTime ??\n (Date.now() - 30 * 24 * 60 * 60 * 1000));\n\n // Record the cache age\n // eslint-disable-next-line @typescript-eslint/dot-notation\n props[\"cacheEntryAge\"] = age;\n }\n\n return snapshotCachedEntry;\n });\n\n // Based on the concurrentSnapshotFetch policy:\n // Either retrieve both the network and cache snapshots concurrently and pick the first to return,\n // or grab the cache value and then the network value if the cache value returns undefined.\n let method: string;\n if (this.hostPolicy.concurrentSnapshotFetch && !this.hostPolicy.summarizerClient) {\n const networkSnapshotP = this.fetchSnapshot(hostSnapshotOptions);\n\n // Ensure that failures on both paths are ignored initially.\n // I.e. if cache fails for some reason, we will proceed with network result.\n // And vice versa - if (for example) client is offline and network request fails first, we\n // do want to attempt to succeed with cached data!\n const promiseRaceWinner = await promiseRaceWithWinner([\n cachedSnapshotP.catch(() => undefined),\n networkSnapshotP.catch(() => undefined),\n ]);\n retrievedSnapshot = promiseRaceWinner.value;\n method = promiseRaceWinner.index === 0 ? \"cache\" : \"network\";\n\n if (retrievedSnapshot === undefined) {\n // if network failed -> wait for cache ( then return network failure)\n // If cache returned empty or failed -> wait for network (success of failure)\n if (promiseRaceWinner.index === 1) {\n retrievedSnapshot = await cachedSnapshotP;\n method = \"cache\";\n }\n if (retrievedSnapshot === undefined) {\n retrievedSnapshot = await networkSnapshotP;\n method = \"network\";\n }\n }\n } else {\n // Note: There's a race condition here - another caller may come past the undefined check\n // while the first caller is awaiting later async code in this block.\n\n retrievedSnapshot = await cachedSnapshotP;\n\n method = retrievedSnapshot !== undefined ? \"cache\" : \"network\";\n\n if (retrievedSnapshot === undefined) {\n retrievedSnapshot = await this.fetchSnapshot(hostSnapshotOptions);\n }\n }\n if (method === \"network\") {\n // eslint-disable-next-line @typescript-eslint/dot-notation\n props[\"cacheEntryAge\"] = undefined;\n }\n event.end({ ...props, method });\n return retrievedSnapshot;\n },\n );\n\n // Successful call, make network calls only\n this.firstVersionCall = false;\n\n this._snapshotSequenceNumber = odspSnapshotCacheValue.sequenceNumber;\n const { snapshotTree, blobs, ops } = odspSnapshotCacheValue;\n // id should be undefined in case of just ops in snapshot.\n let id: string | undefined;\n if (snapshotTree) {\n id = snapshotTree.id;\n assert(id !== undefined, 0x221 /* \"Root tree should contain the id\" */);\n this.setRootTree(id, snapshotTree);\n }\n if (blobs) {\n this.initBlobsCache(blobs);\n }\n\n this.ops = ops;\n return id ? [{ id, treeId: undefined! }] : [];\n }\n\n return getWithRetryForTokenRefresh(async (options) => {\n const storageToken = await this.getStorageToken(options, \"GetVersions\");\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${this.snapshotUrl}/versions?count=${count}`,\n storageToken,\n !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n );\n\n // Fetch the latest snapshot versions for the document\n const response = await PerformanceEvent.timedExecAsync(\n this.logger,\n {\n eventName: \"getVersions\",\n headers: Object.keys(headers).length !== 0 ? true : undefined,\n },\n async () => this.epochTracker.fetchAndParseAsJSON<IDocumentStorageGetVersionsResponse>(url, { headers }, \"versions\"),\n );\n const versionsResponse = response.content;\n if (!versionsResponse) {\n throw new NonRetryableError(\n \"getVersionsReturnedNoResponse\",\n \"No response from /versions endpoint\",\n DriverErrorType.genericNetworkError);\n }\n if (!Array.isArray(versionsResponse.value)) {\n throw new NonRetryableError(\n \"getVersionsReturnedNonArrayResponse\",\n \"Incorrect response from /versions endpoint\",\n DriverErrorType.genericNetworkError);\n }\n return versionsResponse.value.map((version) => {\n // Parse the date from the message\n let date: string | undefined;\n for (const rec of version.message.split(\"\\n\")) {\n const index = rec.indexOf(\":\");\n if (index !== -1 && rec.substr(0, index) === \"Date\") {\n date = rec.substr(index + 1).trim();\n break;\n }\n }\n return {\n date,\n id: version.id,\n treeId: undefined!,\n };\n });\n });\n }\n\n private async fetchSnapshot(hostSnapshotOptions: ISnapshotOptions | undefined) {\n return this.fetchSnapshotCore(hostSnapshotOptions).catch((error) => {\n // Issue #5895:\n // If we are offline, this error is retryable. But that means that RetriableDocumentStorageService\n // will run in circles calling getSnapshotTree, which would result in OdspDocumentStorageService class\n // going getVersions / individual blob download path. This path is very slow, and will not work with\n // delay-loaded data stores and ODSP storage deleting old snapshots and blobs.\n if (typeof error === \"object\" && error !== null) {\n error.canRetry = false;\n }\n throw error;\n });\n }\n\n private async fetchSnapshotCore(hostSnapshotOptions: ISnapshotOptions | undefined) {\n const snapshotOptions: ISnapshotOptions = {\n mds: this.maxSnapshotSizeLimit,\n ...hostSnapshotOptions,\n timeout: hostSnapshotOptions?.timeout ? Math.min(hostSnapshotOptions.timeout, this.maxSnapshotFetchTimeout) : this.maxSnapshotFetchTimeout,\n };\n\n // No limit on size of snapshot or time to fetch, as otherwise we fail all clients to summarize\n if (this.hostPolicy.summarizerClient) {\n snapshotOptions.mds = undefined;\n snapshotOptions.timeout = undefined;\n }\n\n const snapshotDownloader = async (\n finalOdspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n options: ISnapshotOptions | undefined,\n controller?: AbortController,\n ) => {\n return downloadSnapshot(\n finalOdspResolvedUrl,\n storageToken,\n this.logger,\n options,\n this.hostPolicy.fetchBinarySnapshotFormat,\n controller,\n this.epochTracker,\n );\n };\n const putInCache = async (valueWithEpoch: IVersionedValueWithEpoch) => {\n return this.cache.persistedCache.put(\n createCacheSnapshotKey(this.odspResolvedUrl),\n // Epoch tracker will add the epoch and version to the value here. So just send value to cache.\n valueWithEpoch.value,\n );\n };\n const removeEntries = async () => this.cache.persistedCache.removeEntries();\n try {\n const odspSnapshot = await fetchSnapshotWithRedeem(\n this.odspResolvedUrl,\n this.getStorageToken,\n snapshotOptions,\n !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n this.logger,\n snapshotDownloader,\n putInCache,\n removeEntries,\n this.hostPolicy.enableRedeemFallback,\n );\n return odspSnapshot;\n } catch (error) {\n const errorType = error.errorType;\n // If the snapshot size is too big and the host specified the size limitation(specified in hostSnapshotOptions), then don't try to fetch the snapshot again.\n if ((errorType === OdspErrorType.snapshotTooBig && hostSnapshotOptions?.mds !== undefined) && (this.hostPolicy.summarizerClient !== true)) {\n throw error;\n }\n // If the first snapshot request was with blobs and we either timed out or the size was too big, then try to fetch without blobs.\n if ((errorType === OdspErrorType.snapshotTooBig || errorType === OdspErrorType.fetchTimeout) && snapshotOptions.blobs) {\n this.logger.sendErrorEvent({\n eventName: \"TreeLatest_SecondCall\",\n errorType,\n });\n const snapshotOptionsWithoutBlobs: ISnapshotOptions = { ...snapshotOptions, blobs: 0, mds: undefined, timeout: undefined };\n const odspSnapshot = await fetchSnapshotWithRedeem(\n this.odspResolvedUrl,\n this.getStorageToken,\n snapshotOptionsWithoutBlobs,\n !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n this.logger,\n snapshotDownloader,\n putInCache,\n removeEntries,\n this.hostPolicy.enableRedeemFallback,\n );\n return odspSnapshot;\n }\n throw error;\n }\n }\n\n public async write(tree: api.ITree, parents: string[], message: string): Promise<api.IVersion> {\n this.checkSnapshotUrl();\n\n throw new Error(\"Not supported\");\n }\n\n public async uploadSummaryWithContext(summary: api.ISummaryTree, context: ISummaryContext): Promise<string> {\n this.checkSnapshotUrl();\n\n // Enable flushing only if we have single commit summary and this is not the initial summary for an empty file\n if (\".protocol\" in summary.tree && context.ackHandle !== undefined) {\n let retry = 0;\n for (;;) {\n const result = await this.flushCallback();\n const seq = result.lastPersistedSequenceNumber;\n if (seq !== undefined && seq >= context.referenceSequenceNumber) {\n break;\n }\n\n retry++;\n if (retry > 3) {\n this.logger.sendErrorEvent({\n eventName: \"FlushFailure\",\n ...result,\n retry,\n referenceSequenceNumber: context.referenceSequenceNumber,\n });\n break;\n }\n\n this.logger.sendPerformanceEvent({\n eventName: \"FlushExtraCall\",\n ...result,\n retry,\n referenceSequenceNumber: context.referenceSequenceNumber,\n });\n\n await delay(1000 * (result.retryAfter ?? 1));\n }\n }\n\n const id = await PerformanceEvent.timedExecAsync(this.logger,\n { eventName: \"uploadSummaryWithContext\" },\n async () => this.odspSummaryUploadManager.writeSummaryTree(summary, context));\n return id;\n }\n\n public async downloadSummary(commit: api.ISummaryHandle): Promise<api.ISummaryTree> {\n throw new Error(\"Not implemented yet\");\n }\n\n private setRootTree(id: string, tree: api.ISnapshotTree) {\n this.commitCache.set(id, tree);\n }\n\n private initBlobsCache(blobs: Map<string, ArrayBuffer>) {\n this.blobCache.addBlobs(blobs);\n }\n\n private checkSnapshotUrl() {\n if (!this.snapshotUrl) {\n throw new NonRetryableError(\n \"noSnapshotUrlProvided\",\n \"Method failed because no snapshot url was available\",\n DriverErrorType.genericError);\n }\n }\n\n private checkAttachmentPOSTUrl() {\n if (!this.attachmentPOSTUrl) {\n throw new NonRetryableError(\n \"noAttachmentPOSTUrlProvided\",\n \"Method failed because no attachment POST url was available\",\n DriverErrorType.genericError);\n }\n }\n\n private checkAttachmentGETUrl() {\n if (!this.attachmentGETUrl) {\n throw new NonRetryableError(\n \"noAttachmentGETUrlWasProvided\",\n \"Method failed because no attachment GET url was available\",\n DriverErrorType.genericError);\n }\n }\n\n private async readTree(id: string): Promise<api.ISnapshotTree | null> {\n if (!this.snapshotUrl) {\n return null;\n }\n let tree = this.commitCache.get(id);\n if (!tree) {\n tree = await getWithRetryForTokenRefresh(async (options) => {\n const storageToken = await this.getStorageToken(options, \"ReadCommit\");\n const snapshotDownloader = async (url: string, fetchOptions: {[index: string]: any}) => {\n return this.epochTracker.fetchAndParseAsJSON(\n url,\n fetchOptions,\n \"snapshotTree\",\n );\n };\n const snapshot = await fetchSnapshot(\n this.snapshotUrl!,\n storageToken,\n id,\n this.fetchFullSnapshot,\n !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n this.logger,\n snapshotDownloader,\n );\n let treeId = \"\";\n if (snapshot.snapshotTree) {\n assert(snapshot.snapshotTree.id !== undefined, 0x222 /* \"Root tree should contain the id!!\" */);\n treeId = snapshot.snapshotTree.id;\n this.setRootTree(treeId, snapshot.snapshotTree);\n }\n if (snapshot.blobs) {\n this.initBlobsCache(snapshot.blobs);\n }\n // If the version id doesn't match with the id of the tree, then use the id of first tree which in that case\n // will be the actual id of tree to be fetched.\n return this.commitCache.get(id) ?? this.commitCache.get(treeId);\n });\n }\n\n if (!tree) {\n return null;\n }\n\n return tree;\n }\n\n /**\n * Reads a summary tree\n * @param protocolTreeOrId - Protocol snapshot tree or id of the protocol tree\n * @param appTreeId - Id of the app tree\n */\n private async readSummaryTree(protocolTreeOrId: api.ISnapshotTree | string, appTreeId: string): Promise<api.ISnapshotTree> {\n // Load the app and protocol trees and return them\n let hierarchicalProtocolTree: api.ISnapshotTree | null;\n if (typeof (protocolTreeOrId) === \"string\") {\n // Backwards compat for older summaries\n hierarchicalProtocolTree = await this.readTree(protocolTreeOrId);\n } else {\n hierarchicalProtocolTree = protocolTreeOrId;\n }\n\n const hierarchicalAppTree = await this.readTree(appTreeId);\n if (!hierarchicalProtocolTree) {\n throw new Error(\"Invalid protocol tree\");\n }\n\n if (!hierarchicalAppTree) {\n throw new Error(\"Invalid app tree\");\n }\n\n if (hierarchicalProtocolTree.blobs) {\n const attributesBlob = hierarchicalProtocolTree.blobs.attributes;\n if (attributesBlob) {\n this.attributesBlobHandles.add(attributesBlob);\n }\n }\n return this.combineProtocolAndAppSnapshotTree(hierarchicalAppTree, hierarchicalProtocolTree);\n }\n\n private combineProtocolAndAppSnapshotTree(\n hierarchicalAppTree: api.ISnapshotTree,\n hierarchicalProtocolTree: api.ISnapshotTree,\n ) {\n const summarySnapshotTree: api.ISnapshotTree = {\n blobs: {\n ...hierarchicalAppTree.blobs,\n },\n commits: {\n ...hierarchicalAppTree.commits,\n },\n trees: {\n ...hierarchicalAppTree.trees,\n // the app tree could have a .protocol\n // in that case we want to server protocol to override it\n \".protocol\": hierarchicalProtocolTree,\n },\n };\n\n return summarySnapshotTree;\n }\n}\n\n/* eslint-enable max-len */\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"odspDriverUrlResolver.d.ts","sourceRoot":"","sources":["../src/odspDriverUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAkB,MAAM,iCAAiC,CAAC;AAC9F,OAAO,EAAgB,YAAY,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAC9F,OAAO,EAAE,gBAAgB,EAAqC,MAAM,yCAAyC,CAAC;AA4C9G;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,YAAY;;IAGzC,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAwFrD,cAAc,CACvB,WAAW,EAAE,YAAY,EACzB,WAAW,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,iBAAiB,GAChC,OAAO,CAAC,MAAM,CAAC;CAgBrB"}
1
+ {"version":3,"file":"odspDriverUrlResolver.d.ts","sourceRoot":"","sources":["../src/odspDriverUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAkB,MAAM,iCAAiC,CAAC;AAC9F,OAAO,EAAgB,YAAY,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAC9F,OAAO,EAAE,gBAAgB,EAAqC,MAAM,yCAAyC,CAAC;AA6C9G;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,YAAY;;IAGzC,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA0FrD,cAAc,CACvB,WAAW,EAAE,YAAY,EACzB,WAAW,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,iBAAiB,GAChC,OAAO,CAAC,MAAM,CAAC;CAgBrB"}