Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement insertion order support for SharedMap #17580

Conversation

clarenceli-msft
Copy link
Contributor

@github-actions github-actions bot added area: dds Issues related to distributed data structures public api change Changes to a public API base: main PRs targeted against main branch labels Oct 2, 2023
@clarenceli-msft clarenceli-msft requested a review from a team as a code owner October 2, 2023 15:00
@github-actions github-actions bot added the dependencies Pull requests that update a dependency file label Oct 2, 2023
@msfluid-bot
Copy link
Collaborator

msfluid-bot commented Oct 2, 2023

@fluid-example/bundle-size-tests: +32.91 KB
Metric NameBaseline SizeCompare SizeSize Diff
aqueduct.js 443.96 KB 449.98 KB +6.02 KB
connectionState.js 680 Bytes 680 Bytes No change
containerRuntime.js 237.29 KB 237.29 KB No change
loader.js 148.39 KB 148.39 KB No change
map.js 48.43 KB 75.04 KB +26.6 KB
matrix.js 142.21 KB 142.36 KB +145 Bytes
odspDriver.js 90.46 KB 90.46 KB No change
odspPrefetchSnapshot.js 42.13 KB 42.13 KB No change
sharedString.js 162.86 KB 163 KB +145 Bytes
sharedTree2.js 258.88 KB 258.88 KB No change
Total Size 1.68 MB 1.71 MB +32.91 KB

Baseline commit: af58ac2

Generated by 🚫 dangerJS against ee66bde

Copy link
Contributor

@Abe27342 Abe27342 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got through reading existing tests today: I'll start looking through the implementation tomorrow. One comment on the test plan--we should add ordering consistency validation to the map fuzz tests assertMapsAreEquivalent.

packages/dds/map/src/test/mocha/map.order.spec.ts Outdated Show resolved Hide resolved
packages/dds/map/src/test/mocha/map.order.spec.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@Abe27342 Abe27342 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have some comments on top-level state that I'd like clarifications on before thinking too deeply about the logic changes to mapKernel.

packages/dds/map/src/mapKernel.ts Show resolved Hide resolved
/**
* Object to store the message Id's for all set op's
*/
private readonly pendingSetTracker: Map<string, number[]> = new Map();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this different from pendingKeys? Seems like it serves a similar purpose and it'd be great to only store one.

If you can unify them, please update the doc comment on pendingKeys to note the meaning of number[] as you've done here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of pendingKeys is to maintain message IDs associated with all pending ops on a specific key, including both set and delete. In contrast, pendingSetTracker is dedicated solely to tracking pending set messages. There do exist some overlap in functionality between these two data structures.

If we want to unify them, one option is to modify the design of pendingDeleteTracker from a Map<string, number> (which currently stores only the count of pending delete messages) to a Map<string, number[]>. This change would allow pendingDeleteTracker to also store the IDs of pending delete messages. As a result, the combination of pendingSetTracker and the enhanced pendingDeleteTracker could replace the need for pendingKeys completely.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like it's probably conceptually simpler to organize the state more like you've suggested. I'd propose a slightly different organization: map from key to an ordered list of 'events' that occurred at that key. We could use pending message id for those events. Then we'd also maintain lookup from message id to whatever op metadata we need.

I'd rather tackle this kind of thing in a follow-up PR though (maybe before we bring it to main, maybe after, not sure)

packages/dds/map/src/mapKernel.ts Outdated Show resolved Hide resolved
packages/dds/map/src/mapKernel.ts Outdated Show resolved Hide resolved
packages/dds/map/src/mapKernel.ts Show resolved Hide resolved
@clarenceli-msft clarenceli-msft changed the base branch from main to map-creation-order-support October 10, 2023 16:21
Copy link
Contributor

@Abe27342 Abe27342 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looking pretty good. I've reviewed the logic for set/delete and took a cursory glance at summarization concerns. Still need to dig deeper into:

  • clear
  • resubmit
  • local rollback
  • stashed ops (would be ok settling that in a different work item; logic in message handlers looks sane I just doubt we have good coverage of it)
  • finish summarization review

packages/dds/map/src/creationIndexTracker.ts Outdated Show resolved Hide resolved
packages/dds/map/src/creationIndexTracker.ts Outdated Show resolved Hide resolved
packages/dds/map/src/interfaces.ts Outdated Show resolved Hide resolved
previousValue: ILocalValue;

/**
* All associated pending message id's of a local set op, or the insertion index of an ack'd key, or both
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not obvious how this description of the state maps to the type presented. Could you clarify more?

In general nested arrays are a bit of a code smell without qualification (except when dealing with fundamentally N-D data)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added examples to explain it

packages/dds/map/src/creationIndexTracker.ts Outdated Show resolved Hide resolved
if (op.type === "set") {
this.ackPendingSetOp(op, pendingMessageId);
} else if (op.type === "delete") {
// Adjust the keys order if it is already ack'd
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment doesn't look like it applies here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added more detailed comments

packages/dds/map/src/mapKernel.ts Show resolved Hide resolved
packages/dds/map/src/mapKernel.ts Show resolved Hide resolved
packages/dds/map/src/mapKernel.ts Show resolved Hide resolved
}

pendingSetIds.shift();
if (pendingSetIds.length === 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leftover comment

packages/dds/map/src/mapKernel.ts Outdated Show resolved Hide resolved
if (this.pendingKeys.size > 0) {
this.clearExceptPendingKeys();
return;
}
this.clearCore(local);
this.localKeysIndexTracker.clear();
this.pendingSetTracker.clear();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: it's kinda pre-existing, but I feel like if-else control flow here is simpler than the early return for this.pendingKeys.size > 0.

/**
* Object to store the message Id's for all set op's
*/
private readonly pendingSetTracker: Map<string, number[]> = new Map();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like it's probably conceptually simpler to organize the state more like you've suggested. I'd propose a slightly different organization: map from key to an ordered list of 'events' that occurred at that key. We could use pending message id for those events. Then we'd also maintain lookup from message id to whatever op metadata we need.

I'd rather tackle this kind of thing in a follow-up PR though (maybe before we bring it to main, maybe after, not sure)

@@ -386,16 +602,44 @@ export class MapKernel {

/**
* Populate the kernel with the given map data.
*
* If there exixts data created during the detached stage without assigned creation index, it is essential to populate these indices
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than populate implicitly in summary load here, we should populate this explicitly while generating the attach summary. This will make sure we're able to distinguish documents generated with modern versions of the code rather than legacy ones once we move to using something attributable (seq) rather than an index

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it is already covered in the "scenario 2" mentioned in the comments of the function getSerializedStorage. The creation indices are populate explicitly when generating the attach summary.

* If there exixts data created during the detached stage without assigned creation index, it is essential to populate these indices
* (starting from 0) and keep track of their count.
*
* Additionally, for loading data in the old format lacking an index field, it is necessary to populate the corresponding creation index
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great, agreed this is important.

packages/dds/map/src/mapKernel.ts Show resolved Hide resolved
*
* There are two scenarios in which the creation index may be absent:
* 1. When the client is detached, we defer assigning the creation index until the data is about to be summarized.
* 2. When the client is attached, but data was created during the detached stage, the creation indices for that data are still missing.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting. I think that might be an inaccuracy in the harness--the attach summary should be generated before attaching.

type: "delete",
pendingMessageId,
previousValue: localOpMetadata.previousValue,
previousIndex: localOpMetadata.previousIndex,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"firstPendingSetId" is probably better

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even if it's maybe a little inaccurate (it's the first pending set after the most recently submitted delete)

pendingMessageId,
previousValue: localOpMetadata.previousValue,
previousIndex: localOpMetadata.previousIndex,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not undefined was already checked above

Suggested change
};
if (pendingSetIds.length === 0) {

previousValue: localOpMetadata.previousValue,
previousIndex: localOpMetadata.previousIndex,
};

this.submitMessage(op, localMetadata);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems not right that we're using a message id rather than an index here.

NicholasCouri and others added 14 commits October 24, 2023 14:59
…even on setup (microsoft#17964)

## Description
The initial implementation of the performance runs would skip drivers
only on the load and summarize events but would still run once during
initial setup. AFR is timing out even on that step for Matrix tests. In
order to avoid this timeout, we are now enforcing the skip even during
the initial setup.
## Description

In order to better understand the scenarios where T9S is triggering
NoJoinOps due to clients disappearing, we need the verbose logs to be
logged for all the containers and not in 50% of them. When we have a fix
for it or If the amount of space on Kusto increases dramatically we
might re-visit and go back to 50%.
… Connection Manager being disposed before new connection setup (microsoft#17962)

## Description
Latest event
(fluid:telemetry:RouterliciousDriver:DeltaConnection:ConnectDocumentSuccess)
to try to address the NoJoinOps happening in tinylicious seems to
indicate a new client is added, join op is sent over the wire but there
is no additional logging for that clientid. The current theory is the
connection manager being disposed of while waiting for the await
docService.connectToDeltaStream to return. We are also adding additional
verbose logs to better understand if it still happens.
Fix few errors found during alpha/beta publishing. The changes are
around:
1. setPackageTypesField flub command
2. Resolving an error validation check.
Update api-extractor-base config to not generate rollups by default.
Enable rollups in tree2, devtools, api-extractor-documenter
It turned out that `lib` build is missing for the
`@fluid-experimental/property-proxy` package since of misconfiguration.
This PR fixes the issue.
…n garbage collector (microsoft#17948)

This PR moves the gc tomsbtone configs initalization into one place in
garbage collector configs. Currently, the same configs are initialized
in DataStores, DataStoreContext and GarbageCollector making it possible
for them to get out of sync. Also, changing it requires changing them
everywhere making changes more complex and prone to errors.
…#17972)

SharedListNode.insert*() needed adjustment to accept the new
factory-created content.
SharedListNode.move*() needed adjustment to accept to accept a
SharedListNode as source.

Testing also uncovered and fixed a couple of minor bugs in the move
implementation:
* Use 'boxedAt()' when validating that the items in the source list
comply with the destination type.
* The adjustment of the destination index wasn't quite right.

---------

Co-authored-by: Noah Encke <78610362+noencke@users.noreply.github.com>
## Description

Related to ADO:6011. Also, it was brought to my attention by
@clarenceli-msft.

The issues here were:
- `this.clientSequenceNumber` was only incremented at read time when
grouped batching was enabled. This means that that when batches are
ungrouped, there can be two messages with the same client sequence
number, same sequence number and different content.
- grouped batching uses fake client sequence numbers, just to
differentiate between messages within the same batch.
Some fixes for the Node.js cluster module POC from microsoft#17243.

## Description

There were 2 primary bugs:

1. When not setting up a server to perform sticky-session load balancing
for Socket.io, we can't just have a blank server. So I added
`NullHttpServer` and `NullWebServer` as dummy placeholders for various
listeners assigned in `runner.ts` since the primary thread in this case
isn't actually doing anything but load-balancing.
2. The config defaults were all over the place for the
NodeClusterWebServerFactory, so I unified those in the constructor. This
solved a bug where workers were timing out instantly, because there was
no timeout config.
@clarenceli-msft clarenceli-msft requested review from a team as code owners November 16, 2023 21:15
@clarenceli-msft clarenceli-msft marked this pull request as draft November 16, 2023 21:16
Copy link
Contributor

🔗 Found some broken links! 💔

Run a link check locally to find them. See
https://github.com/microsoft/FluidFramework/wiki/Checking-for-broken-links-in-the-documentation for more information.

linkcheck output


> fluidframework-docs@0.25.0 ci:linkcheck /home/runner/work/FluidFramework/FluidFramework/docs
> start-server-and-test ci:start http://localhost:1313 linkcheck:full

1: starting server using command "npm run ci:start"
and when url "[ 'http://localhost:1313' ]" is responding with HTTP status code 200
running tests using command "npm run linkcheck:full"


> fluidframework-docs@0.25.0 ci:start
> http-server ./public --port 1313 --silent


> fluidframework-docs@0.25.0 linkcheck:full
> npm run linkcheck:fast -- --external


> fluidframework-docs@0.25.0 linkcheck:fast
> linkcheck http://localhost:1313 --skip-file skipped-urls.txt --external

Crawling...

http://localhost:1313/docs/apis/azure-client/
- (930:10) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)
- (930:10) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)

http://localhost:1313/docs/apis/azure-client/itokenclaims-interface/
- (842:3) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)
- (842:3) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)

http://localhost:1313/docs/apis/azure-client/itokenresponse-interface/
- (885:8) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)
- (898:8) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)
- (885:8) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)
- (898:8) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)

http://localhost:1313/docs/apis/location-redirection-utils/
- (833:52) => http://localhost:1313/docs/apis/container-loader/-entrypoint (HTTP 404)
- (833:52) => http://localhost:1313/docs/apis/container-loader/-entrypoint (HTTP 404)

http://localhost:1313/docs/apis/protocol-definitions/
- (1293:10) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)
- (1293:10) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)

http://localhost:1313/docs/apis/protocol-definitions/itokenclaims-interface/
- (835:3) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)
- (835:3) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)

http://localhost:1313/docs/apis/react-inputs/icollaborativetextareaprops-interface/
- (886:45) 'read-only' => https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-readonly (HTTP 200 but missing anchor)
- (943:45) 'read-only' => https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-readonly (HTTP 200 but missing anchor)
- (886:45) 'read-only' => https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-readonly (HTTP 200 but missing anchor)
- (943:45) 'read-only' => https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-readonly (HTTP 200 but missing anchor)

http://localhost:1313/docs/apis/routerlicious-driver/itokenresponse-interface/
- (878:8) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)
- (891:8) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)
- (878:8) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)
- (891:8) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)

http://localhost:1313/docs/apis/routerlicious-driver/itokenservice-interface/
- (858:121) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)
- (866:19) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)
- (858:121) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)
- (866:19) 'JSON Web..' => https://jwt.io/introduction/ (connection failed)

http://localhost:1313/docs/apis/runtime-definitions/
- (1850:37) 'https://..' => https://datatracker.ietf.org/doc/html/rfc4122%29 (HTTP 404)
- (1850:37) 'https://..' => https://datatracker.ietf.org/doc/html/rfc4122%29 (HTTP 404)

http://localhost:1313/docs/apis/tree/
- (4170:210) 'https://..' => https://github.com/microsoft/FluidFramework/blob/main/packages/loader/container-utils/src/error.ts (HTTP 404)
- (4170:210) 'https://..' => https://github.com/microsoft/FluidFramework/blob/main/packages/loader/container-utils/src/error.ts (HTTP 404)

http://localhost:1313/docs/apis/tree2/internaltypes-namespace/
- (904:15) 'https://..' => https://dev.azure.com/intentional/intent/_wiki/wikis/NP%20Platform/7146/Nominal-vs-Structural-Types (HTTP 302 => 203)
  - redirect path:
    - https://dev.azure.com/intentional/intent/_wiki/wikis/NP%20Platform/7146/Nominal-vs-Structural-Types (302)
    - https://spsprodwus24.vssps.visualstudio.com/_signin?realm=dev.azure.com&reply_to=https%3A%2F%2Fdev.azure.com%2Fintentional%2Fintent%2F_wiki%2Fwikis%2FNP%2520Platform%2F7146%2FNominal-vs-Structural-Types&redirect=1&hid=4a05b22b-56d9-4015-84eb-356e83cc96ca&context=eyJodCI6MiwiaGlkIjoiMTg1NjAzMjgtMWMwMC00NWE4LTg0OGYtZDdmMTJlMzg0YjAwIiwicXMiOnt9LCJyciI6IiIsInZoIjoiIiwiY3YiOiIiLCJjcyI6IiJ90#ctx=eyJTaWduSW5Db29raWVEb21haW5zIjpbImh0dHBzOi8vbG9naW4ubWljcm9zb2Z0b25saW5lLmNvbSIsImh0dHBzOi8vbG9naW4ubWljcm9zb2Z0b25saW5lLmNvbSJdfQ2 (203)
- (904:15) 'https://..' => https://dev.azure.com/intentional/intent/_wiki/wikis/NP%20Platform/7146/Nominal-vs-Structural-Types (HTTP 302 => 203)
  - redirect path:
    - https://dev.azure.com/intentional/intent/_wiki/wikis/NP%20Platform/7146/Nominal-vs-Structural-Types (302)
    - https://spsprodwus24.vssps.visualstudio.com/_signin?realm=dev.azure.com&reply_to=https%3A%2F%2Fdev.azure.com%2Fintentional%2Fintent%2F_wiki%2Fwikis%2FNP%2520Platform%2F7146%2FNominal-vs-Structural-Types&redirect=1&hid=4a05b22b-56d9-4015-84eb-356e83cc96ca&context=eyJodCI6MiwiaGlkIjoiMTg1NjAzMjgtMWMwMC00NWE4LTg0OGYtZDdmMTJlMzg0YjAwIiwicXMiOnt9LCJyciI6IiIsInZoIjoiIiwiY3YiOiIiLCJjcyI6IiJ90#ctx=eyJTaWduSW5Db29raWVEb21haW5zIjpbImh0dHBzOi8vbG9naW4ubWljcm9zb2Z0b25saW5lLmNvbSIsImh0dHBzOi8vbG9naW4ubWljcm9zb2Z0b25saW5lLmNvbSJdfQ2 (203)

http://localhost:1313/docs/apis/tree2/internaltypes/makenominal-interface/
- (837:8) 'https://..' => https://dev.azure.com/intentional/intent/_wiki/wikis/NP%20Platform/7146/Nominal-vs-Structural-Types (HTTP 302 => 203)
  - redirect path:
    - https://dev.azure.com/intentional/intent/_wiki/wikis/NP%20Platform/7146/Nominal-vs-Structural-Types (302)
    - https://spsprodwus24.vssps.visualstudio.com/_signin?realm=dev.azure.com&reply_to=https%3A%2F%2Fdev.azure.com%2Fintentional%2Fintent%2F_wiki%2Fwikis%2FNP%2520Platform%2F7146%2FNominal-vs-Structural-Types&redirect=1&hid=4a05b22b-56d9-4015-84eb-356e83cc96ca&context=eyJodCI6MiwiaGlkIjoiMTg1NjAzMjgtMWMwMC00NWE4LTg0OGYtZDdmMTJlMzg0YjAwIiwicXMiOnt9LCJyciI6IiIsInZoIjoiIiwiY3YiOiIiLCJjcyI6IiJ90#ctx=eyJTaWduSW5Db29raWVEb21haW5zIjpbImh0dHBzOi8vbG9naW4ubWljcm9zb2Z0b25saW5lLmNvbSIsImh0dHBzOi8vbG9naW4ubWljcm9zb2Z0b25saW5lLmNvbSJdfQ2 (203)
- (837:8) 'https://..' => https://dev.azure.com/intentional/intent/_wiki/wikis/NP%20Platform/7146/Nominal-vs-Structural-Types (HTTP 302 => 203)
  - redirect path:
    - https://dev.azure.com/intentional/intent/_wiki/wikis/NP%20Platform/7146/Nominal-vs-Structural-Types (302)
    - https://spsprodwus24.vssps.visualstudio.com/_signin?realm=dev.azure.com&reply_to=https%3A%2F%2Fdev.azure.com%2Fintentional%2Fintent%2F_wiki%2Fwikis%2FNP%2520Platform%2F7146%2FNominal-vs-Structural-Types&redirect=1&hid=4a05b22b-56d9-4015-84eb-356e83cc96ca&context=eyJodCI6MiwiaGlkIjoiMTg1NjAzMjgtMWMwMC00NWE4LTg0OGYtZDdmMTJlMzg0YjAwIiwicXMiOnt9LCJyciI6IiIsInZoIjoiIiwiY3YiOiIiLCJjcyI6IiJ90#ctx=eyJTaWduSW5Db29raWVEb21haW5zIjpbImh0dHBzOi8vbG9naW4ubWljcm9zb2Z0b25saW5lLmNvbSIsImh0dHBzOi8vbG9naW4ubWljcm9zb2Z0b25saW5lLmNvbSJdfQ2 (203)

http://localhost:1313/docs/build/bundlers/
- (843:233) 'here' => https://github.com/microsoft/FluidFramework/blob/a4c38234a920abe9b54b1c26a14c0a8e430cd3fa/packages/tools/webpack-fluid-loader/webpack.config.js#L37 (HTTP 200 but missing anchor)

http://localhost:1313/docs/deployment/service-options/
- (848:72) 'Routerli..' => https://github.com/microsoft/FluidFramework/tree/main/server#readme (HTTP 200 but missing anchor)
- (850:168) 'Routerli..' => https://github.com/microsoft/FluidFramework/tree/main/server#readme (HTTP 200 but missing anchor)

http://localhost:1313/docs/faq/
- (927:87) 'Routerli..' => https://github.com/microsoft/FluidFramework/tree/main/server#readme (HTTP 200 but missing anchor)

http://localhost:1313/docs/testing/telemetry/
- (848:3) 'ILoaderP..' => https://github.com/microsoft/FluidFramework/blob/main/packages/loader/container-loader/src/loader.ts#L313 (HTTP 200 but missing anchor)


Stats:
  259536 links
    2496 destination URLs
       2 URLs ignored
      29 warnings
       5 errors

 ELIFECYCLE  Command failed with exit code 1.

@scarlettjlee
Copy link
Contributor

@clarenceli-msft, what kind of feedback are you looking for on this review since it's marked as Draft?

@clarenceli-msft
Copy link
Contributor Author

clarenceli-msft commented Nov 17, 2023

@clarenceli-msft, what kind of feedback are you looking for on this review since it's marked as Draft?

I am closing this PR. Originally, I intended to merge the updates into a feature branch instead of main. While resolving conflicts, I fetched from the main branch, but it appears like I forgot to synchronize the target branch with the main. Consequently, the fetch/pull operation brought all the commits targeting the main branch (since the last update time) to this PR. I tried using cherry-pick but unable to clean it up, I have opened a new PR #18376 to exclusively include the contents that I intend to commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: dds Issues related to distributed data structures base: main PRs targeted against main branch dependencies Pull requests that update a dependency file public api change Changes to a public API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet