Introducing emails and pubkeys stores instead of contacts#3445
Introducing emails and pubkeys stores instead of contacts#3445
emails and pubkeys stores instead of contacts#3445Conversation
|
@tomholub What do you think about it? As each array element in |
tomholub
left a comment
There was a problem hiding this comment.
A clever hack. This would have to be documented better, don't be afraid to write some prose because it's otherwise not obvious at all.
For tests, try to give it knowingly wrong behavior, and see if anything breaks. I imagine something should break.
|
@tomholub I have populated the store with 12500 dummy records, half of them |
|
You can try this. The code should be commented thoroughly so that it's clear what is it trying to do, and why. |
emails and pubkeys stores instead of contacts
|
For the client field - it was used to decide whether to attach public key or not. Let's have the following logic:
All of this logic only makes the public key attach button either activated or not automatically. User can still change it by clicking on the icon before actually sending the message.
Thanks! |
tomholub
left a comment
There was a problem hiding this comment.
Looks directionally good 👍 I'll scrutinize the details later.
extension/chrome/elements/compose-modules/compose-my-pubkey-module.ts
Outdated
Show resolved
Hide resolved
extension/chrome/elements/compose-modules/compose-storage-module.ts
Outdated
Show resolved
Hide resolved
|
|
||
| try { | ||
| db = await ContactStore.dbOpen(); // takes 4-10 ms first time | ||
| await moveContactsToEmailsAndPubkeys(db); |
There was a problem hiding this comment.
@tomholub this is the piece of code I was referring to when talking about contacts migration.
It would be more convenient to perform migration inside dbOpen() call. Thus we'll be able to delete contacts store right after successful conversion to emails and pubkeys.
We can, for example, pass a list of functions to dbOpen to nicely inject transformations so they don't clutter ContactStore code?
There was a problem hiding this comment.
or, perhaps, ContactStore.update will cause errors when called from inside upgrade transaction
There was a problem hiding this comment.
We can do all of this in ContactStore itself, no need to bring the migration out to here.
There was a problem hiding this comment.
We can do all of this in ContactStore itself, no need to bring the migration out to here.
Looks like there is a problem with this approach. IDTransaction docs say that transaction is automatically completed when it goes out of scope, and this disallows usage of async function in onupgradeneeded etc.. They are fired alright, but the transaction is closed by the time the actual processing occurs (before waiting for the promise returned by onupgradeneeded handler to be resolved). I searched the github for projects where an async function is used as event handler, found only a small project https://github.com/SourceCodeBot/crudodb (I suspect they haven't tested it properly).
The general approach for transactional operations is (though I haven't found this exact requirement in IndexedDB specs) -- a handler must immediately open a new request, otherwise the transaction will be auto-completed.
We can't convert contacts to pubkeys/emails in a completely synchronized way because of async KeyUtil.parse function.
(This is a point for another discussion -- KeyUtil.parse is async only because it uses a Stream API approach for dearmoring of potentially large messages. As the keys are small, we may think about a sync implementation of KeyUtil.parse)
Still, maybe it's user-unfriendly to "hang" (will it hang?) the browser window for the process of database upgrade, converting multiple contacts, so it makes sense to keep the conversion out of the upgrade handler. The drawback is that the empty contacts table will be lying around until the next upgrade.
There was a problem hiding this comment.
Still, maybe it's user-unfriendly to "hang" (will it hang?) the browser window for the process of database upgrade, converting multiple contacts, so it makes sense to keep the conversion out of the upgrade handler. The drawback is that the empty contacts table will be lying around until the next upgrade.
It will possibly hang the whole browser when we do something like this in background page. Also depends on contacts count. For 50 contacts, not a problem. For 1000 contacts - possible problem.
I think our most reasonable chance is to do a migration of database structure itself, fire off async migration of the actual database, and hope for the best.
If the actual migration does not finish successfully, then on next migration it will be retried (like a browser restart). I think that's ok as long as there is this retry in place.
Best would be to then not migrate all contacts in one gigantic transaction, but one by one. If one of the transactions throws an error because whatever (parsing, concurency, etc), it would not fail the whole migration. 100 keys already migrated, key 101 failed, 50 more to go - the failed one gets catched and skipped, and it will chug along for the remaining 50 keys. Then next time it only has to retry one.
There was a problem hiding this comment.
I have implemented migration in batches of 50, but it's going to throw on an error and crash the extension.
If we skip the errored batch, this portion of contacts won't be available for search -- is this what you're after?
There was a problem hiding this comment.
When there is an error, it's better to skip a batch then stop half way through the migration.
There was a problem hiding this comment.
Will the skipped batch get retried (without any special retry logic) next time I restart the browser?
There was a problem hiding this comment.
The conversion stop at the failed batch with the current implementation.
as contacts store objects are deleted within the same transaction as populating new stores, the contacts from the failed batch will remain in the database, thus they will be retried on subsequent browser restart.
|
I tested most of the use cases. Do you have any other suggestions on what to test? |
|
Test-wise, I think it's well covered. I'll take another look at the code. |
tomholub
left a comment
There was a problem hiding this comment.
All looks good - a few comments.
(still need to review contact-store.ts closer).
Thanks!
| name: string | null; | ||
| pubkey: Key | null; | ||
| pubkey: Key | undefined; | ||
| has_pgp: 0 | 1; |
There was a problem hiding this comment.
Since we are doing a migration anyway, could we rename these to be consistently camelCase? To use hasPgp, lastUse etc.
There was a problem hiding this comment.
This is a purely DTO class. We can of course refactor it in this PR, making it grow even bigger.
This PR uses
searchindex onsearchablefield instead ofindex_has_pgp, so we can removehas_pgpfield.This particular step can help us measure performance as compared to
index_has_pgpusageclose #3332