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

Replication state #60

Merged
merged 21 commits into from
Apr 17, 2023
Merged

Replication state #60

merged 21 commits into from
Apr 17, 2023

Conversation

sethvincent
Copy link
Contributor

@sethvincent sethvincent commented Jan 17, 2023

Closes #51.

This pr provides progress tracking of replication between a core and its peers.

Based largely on https://github.com/digidem/hypercore-replication-progress/

@sethvincent sethvincent changed the base branch from sync to coreReplicator January 17, 2023 00:42
@sethvincent sethvincent marked this pull request as ready for review January 17, 2023 00:42
@gmaclennan
Copy link
Member

This will need some adjustments if #61 is the way forward.

Also maybe we can brainstorm how this might work for the blob store? I wrote an initial implementation in #62. I think we might need to handle it differently because replication being "complete" is not as simple for the blob store - for other stores our aim is to sync everything, so when the peer and local have everything shared, we consider replication "done". However with the blobs we will only be syncing previews and thumbnails from other peers (not originals) when syncing phones, and in the future will have more complicated selective sync. Also we likely want to track "files" rather than blocks (since blobs are split into multiple blocks). I can see a way to do this for "download" progress, but tracking uploads to a peer and whether those are "done" is more complicated. Maybe we could listen to and track peer "wants"? Some joint thinking on this could be helpful.

@sethvincent sethvincent changed the base branch from coreReplicator to main February 2, 2023 16:16
@@ -40,3 +42,37 @@ export function replicate(cm1, cm2) {
])
}
}

export async function waitForCores (coreManager, keys) {
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 moved these functions into the core-manager helpers file. Haven't imported them into the core-manager tests yet but can do that.

if (hasKeys(keys, allKeys)) return
return new Promise(res => {
coreManager.on('add-core', async function onAddCore ({ key, core }) {
await core.ready()
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 await core.ready() here for convenience. Did a quick check to make sure that still works for the core-manager tests and it seems fine.

} = {}) {
const db = new Sqlite(':memory:')
const keyManager = new KeyManager(rootKey)
return new CoreManager({
db,
keyManager,
storage: RAM,
projectKey
projectKey,
projectSecretKey,
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 found it was necessary to be able to pass the secret key here.

@sethvincent
Copy link
Contributor Author

I have a few tests to add still but otherwise this is ready for review.

@sethvincent
Copy link
Contributor Author

Fixed the weird stalling test 🎉

Copy link
Member

@gmaclennan gmaclennan left a comment

Choose a reason for hiding this comment

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

I haven't read through the tests yet, but reviewed sync/replication-state.js. I wouldn't normally comment on performance questions, but I think a lot of this code is in "hot" code paths, that are going to be called multiple times. In general I think it is better for perf to directly use iterators in for...of statements, rather than converting them to arrays and then using the array iteration methods (map, reduce, filter). I believe converting to an array is already going to iterate through them once, and then has the memory overhead of creating the array, which then needs to be garbage collected.
Also, while I am a Array.reduce() fan, I keep seeing feedback that people find it hard to understand code that uses reduce(), so maybe using for...of can be better for readability too.

lib/sync/replication-state.js Outdated Show resolved Hide resolved
lib/sync/replication-state.js Outdated Show resolved Hide resolved
lib/sync/replication-state.js Show resolved Hide resolved
lib/sync/replication-state.js Outdated Show resolved Hide resolved
return obj
}, {})

const synced = this.isSynced()
Copy link
Member

Choose a reason for hiding this comment

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

Because this getter might be accessed frequently, maybe just copy-paste the isSynced() code into the loop/reducer above, to avoid iterating through the states twice.

lib/sync/replication-state.js Outdated Show resolved Hide resolved
lib/sync/replication-state.js Outdated Show resolved Hide resolved
lib/sync/replication-state.js Outdated Show resolved Hide resolved
lib/sync/replication-state.js Outdated Show resolved Hide resolved
lib/sync/replication-state.js Show resolved Hide resolved
sethvincent and others added 2 commits March 10, 2023 10:19
Co-authored-by: Gregor MacLennan <gmaclennan@digital-democracy.org>
Co-authored-by: Gregor MacLennan <gmaclennan@digital-democracy.org>
@sethvincent sethvincent deleted the replication-state branch April 17, 2023 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Track replication state
2 participants