internal: incomplete vault systems behind feature flag (#2340)

This commit is contained in:
Mo
2023-06-30 09:01:56 -05:00
committed by GitHub
parent d16e401bb9
commit b032eb9c9b
638 changed files with 20321 additions and 4813 deletions

View File

@@ -10,10 +10,17 @@ import {
PayloadEmitSource,
PayloadTimestampDefaults,
getIncrementedDirtyIndex,
Predicate,
} from '@standardnotes/models'
import { arrayByRemovingFromIndex, extendArray, UuidGenerator } from '@standardnotes/utils'
import { SNSyncService } from '../Sync/SyncService'
import { AbstractService, InternalEventBusInterface, SyncEvent } from '@standardnotes/services'
import {
AbstractService,
InternalEventBusInterface,
MutatorClientInterface,
SingletonManagerInterface,
SyncEvent,
} from '@standardnotes/services'
/**
* The singleton manager allow consumers to ensure that only 1 item exists of a certain
@@ -26,7 +33,7 @@ import { AbstractService, InternalEventBusInterface, SyncEvent } from '@standard
* 2. Items can override isSingleton, singletonPredicate, and strategyWhenConflictingWithItem (optional)
* to automatically gain singleton resolution.
*/
export class SNSingletonManager extends AbstractService {
export class SNSingletonManager extends AbstractService implements SingletonManagerInterface {
private resolveQueue: DecryptedItemInterface[] = []
private removeItemObserver!: () => void
@@ -34,6 +41,7 @@ export class SNSingletonManager extends AbstractService {
constructor(
private itemManager: ItemManager,
private mutator: MutatorClientInterface,
private payloadManager: PayloadManager,
private syncService: SNSyncService,
protected override internalEventBus: InternalEventBusInterface,
@@ -44,6 +52,7 @@ export class SNSingletonManager extends AbstractService {
public override deinit(): void {
;(this.syncService as unknown) = undefined
;(this.mutator as unknown) = undefined
;(this.itemManager as unknown) = undefined
;(this.payloadManager as unknown) = undefined
@@ -148,7 +157,7 @@ export class SNSingletonManager extends AbstractService {
})
const deleteItems = arrayByRemovingFromIndex(earliestFirst, 0)
await this.itemManager.setItemsToBeDeleted(deleteItems)
await this.mutator.setItemsToBeDeleted(deleteItems)
}
public findSingleton<T extends DecryptedItemInterface>(
@@ -222,7 +231,66 @@ export class SNSingletonManager extends AbstractService {
...PayloadTimestampDefaults(),
})
const item = await this.itemManager.emitItemFromPayload(dirtyPayload, PayloadEmitSource.LocalInserted)
const item = await this.mutator.emitItemFromPayload(dirtyPayload, PayloadEmitSource.LocalInserted)
void this.syncService.sync({ sourceDescription: 'After find or create singleton' })
return item as T
}
public async findOrCreateSingleton<
C extends ItemContent = ItemContent,
T extends DecryptedItemInterface<C> = DecryptedItemInterface<C>,
>(predicate: Predicate<T>, contentType: ContentType, createContent: ItemContent): Promise<T> {
const existingItems = this.itemManager.itemsMatchingPredicate<T>(contentType, predicate)
if (existingItems.length > 0) {
return existingItems[0]
}
/** Item not found, safe to create after full sync has completed */
if (!this.syncService.getLastSyncDate()) {
/**
* Add a temporary observer in case of long-running sync request, where
* the item we're looking for ends up resolving early or in the middle.
*/
let matchingItem: DecryptedItemInterface | undefined
const removeObserver = this.itemManager.addObserver(contentType, ({ inserted }) => {
if (inserted.length > 0) {
const matchingItems = inserted.filter((i) => i.satisfiesPredicate(predicate))
if (matchingItems.length > 0) {
matchingItem = matchingItems[0]
}
}
})
await this.syncService.sync({ sourceDescription: 'Find or create singleton, before any sync has completed' })
removeObserver()
if (matchingItem) {
return matchingItem as T
}
/** Check again */
const refreshedItems = this.itemManager.itemsMatchingPredicate<T>(contentType, predicate)
if (refreshedItems.length > 0) {
return refreshedItems[0] as T
}
}
/** Safe to create */
const dirtyPayload = new DecryptedPayload({
uuid: UuidGenerator.GenerateUuid(),
content_type: contentType,
content: createContent,
dirty: true,
dirtyIndex: getIncrementedDirtyIndex(),
...PayloadTimestampDefaults(),
})
const item = await this.mutator.emitItemFromPayload(dirtyPayload, PayloadEmitSource.LocalInserted)
void this.syncService.sync({ sourceDescription: 'After find or create singleton' })