-
Notifications
You must be signed in to change notification settings - Fork 910
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 IndexedDB LRU Reference Delegate, add LRU tests #1224
Conversation
Oops, lint errors. Will assign back shortly. |
Ok, lint stuff fixed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I flagged a bunch of nits that you can push back on, and may have found one issue. Despite the amount of feedback (sorry), I think this generally looks good. :-)
packages/firestore/test/unit/local/lru_garbage_collector.test.ts
Outdated
Show resolved
Hide resolved
packages/firestore/test/unit/local/lru_garbage_collector.test.ts
Outdated
Show resolved
Hide resolved
packages/firestore/test/unit/local/lru_garbage_collector.test.ts
Outdated
Show resolved
Hide resolved
packages/firestore/test/unit/local/lru_garbage_collector.test.ts
Outdated
Show resolved
Hide resolved
packages/firestore/test/unit/local/lru_garbage_collector.test.ts
Outdated
Show resolved
Hide resolved
…db_mutation_queue.ts
@mikelehen fyi, I'm also going to create an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! A couple potential nits and I'm still concerned about SentinelRow / sentinelKeyStore() being defined as distinct from the TargetDocuments schema in indexeddb_schema.ts, but otherwise looking good.
}); | ||
return this.db.getQueryCache().updateQueryData(txn, updated); | ||
getTargetCount(txn: PersistenceTransaction): PersistencePromise<number> { | ||
return this.db.getQueryCache().getQueryCount(txn); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to change this to getTargetCount() too, or is this a preexisting issue?
index: DbTargetDocument.documentTargetsIndex | ||
}, | ||
([targetId, docKey], { path, sequenceNumber }) => { | ||
if (targetId === 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh! I assumed that only documents not belonging to a target would have a sentinel row. But I guess every document will have a sentinel row? Is the sequence number for a non-0 targetId row still meaningful? I assumed only the sequence number on the DbTarget row would matter if a document belongs to a target. Yes?
Anyway, I think these questions should be answered in comments in the code. And I think indexeddb_schema.ts is the right place to do that. And to do that, we'll need to include the sentinel row schema in indexeddb_schema.ts as I've requested elsewhere. :-)
/** | ||
* The sentinel key store is the same as the DbTargetDocument store, but allows for | ||
* reading and writing sequence numbers as part of the value stored. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel pretty strongly that indexeddb_schema.ts should continue to be a complete and authoritative description of our schema. So sequenceNumber
should be included there.
Having sentinelKey() and sentinelRow() helpers here seems useful and good (and consistent with Android), but sentinelKeyStore() strongly communicates to me that there's a separate object store for these sentinel rows, which is not what we've actually implemented. I'd be fine with moving them to a separate store, but if they're in the "targetDocuments" object store, calling it something else is confusing to me.
So can we drop SentinelRow and sentinelKeyStore() from here, and just define "sequenceNumber" as part of the DbTargetDocument schema?
docKey: DocumentKey | ||
): PersistencePromise<void> { | ||
return PersistencePromise.waitFor([ | ||
sentinelKeyStore(txn).delete(sentinelKey(docKey)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still have mixed feelings about this. I liked having individual object stores owned by a specific component. That way it's easy for me to consider all of the interactions within that store together. I'm curious why we didn't just have a separate store for the sentinel rows, but I assume there was a good reason and that ship has probably sailed anyway.
So I'm fine with this as-is, except per my other comments I think we should avoid sentinelKeyStore()
since it suggests there is a separate store, which is not the case.
Swap out priority queue for a sorted set
…et document store
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I think I've addressed everything? Unless github is still hiding things from me...
docKey: DocumentKey | ||
): PersistencePromise<void> { | ||
return PersistencePromise.waitFor([ | ||
sentinelKeyStore(txn).delete(sentinelKey(docKey)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason sentinel rows are interleaved with target-document rows is efficiency. The current algorithm for identifying orphaned documents is a scan. Using a separate store would require scanning that store, and then for each row, doing a lookup in the target-document store. FWIW, we tried this in sqlite on Android by adding a sequence number column to each remote document. It was faster to add a nullable column to the target-document many-to-many table that only had values where targetId == 0
.
/** | ||
* The sentinel key store is the same as the DbTargetDocument store, but allows for | ||
* reading and writing sequence numbers as part of the value stored. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My main concern is that I don't want the query cache to have access to the sequence number. It's not present for any rows that the query cache would be dealing with. I've removed SentinelRow
and sentinelKeyStore()
though. I've added an assert to the constructor for DbTargetDocument
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with a couple nits.
Requested rename from firebase/firebase-js-sdk#1224, targets is a better name than queries for internal portions of the SDK.
Adds:
LruGarbageCollector
which implements the steps for LRU garbage collectionjava.util.PriorityQueue
LruDelegate
interface, which specifies what is needed for a persistence layer for LRU GCReferenceDelegate
interface, which handles lifecycle hooks for document references and unreferencesIndexedDbLruDelegate
, implementsReferenceDelegate
andLruDelegate
forIndexedDbPersistence
IndexedDbPersistence
, and as such contains a few casts that will be removed once the generic interfaces support the needed methods.Android Port: https://github.com/FirebasePrivate/firebase-android-sdk/pull/190
iOS Port: firebase/firebase-ios-sdk#1600