Skip to content

Commit 758aeea

Browse files
Improved correctness of added and removed pages when child tasks are involved
1 parent c11cab4 commit 758aeea

File tree

2 files changed

+58
-13
lines changed

2 files changed

+58
-13
lines changed

Sources/CodableDatastore/Persistence/Disk Persistence/Datastore/DatastoreIndex.swift

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -658,15 +658,22 @@ extension DiskPersistence.Datastore.Index {
658658
let originalOrderedPages = manifest.orderedPages
659659
for (index, pageInfo) in originalOrderedPages.enumerated() {
660660
switch pageInfo {
661-
case .removed(let pageID):
662-
removedPages.insert(await datastore.page(for: .init(index: id, page: pageID)))
663-
/// Skip previously removed entries — for now, we don't want to list them.
661+
case .removed:
662+
/// Skip previously removed entries, unless this index is based on a transient index, and the removed entry was from before the transaction began.
663+
if !isPersisted {
664+
newOrderedPages.append(pageInfo)
665+
}
664666
continue
665667
case .existing(let pageID), .added(let pageID):
666-
/// If we are processing an earlier page, just include it as an existing page. If we are finished inserting, actually create the pages first, then import the existing page.
668+
/// If we are processing an earlier page or are finished inserting, just include it as an existing page.
667669
guard index >= insertionPage, !finishedInserting else {
668-
/// Add the specified page as an existing page.
669-
newOrderedPages.append(.existing(pageID))
670+
if isPersisted {
671+
/// Add the specified page as an existing page, since this is an index based on persisted data.
672+
newOrderedPages.append(.existing(pageID))
673+
} else {
674+
/// Add the specified page as is since we are working off a transient index, and would lose the fact that it may have been recently added otherwise.
675+
newOrderedPages.append(pageInfo)
676+
}
670677
continue
671678
}
672679

@@ -678,8 +685,10 @@ extension DiskPersistence.Datastore.Index {
678685
throw DatastoreInterfaceError.staleCursor
679686
}
680687

688+
let existingPage = insertAfter.page
689+
681690
/// Split the existing page into two halves.
682-
let existingPageBlocks = try await insertAfter.page.blocks.reduce(into: [DatastorePageEntryBlock]()) { $0.append($1) }
691+
let existingPageBlocks = try await existingPage.blocks.reduce(into: [DatastorePageEntryBlock]()) { $0.append($1) }
683692
let firstHalf = existingPageBlocks[...insertAfter.blockIndex]
684693
let remainingBlocks = existingPageBlocks[(insertAfter.blockIndex+1)...]
685694

@@ -702,8 +711,12 @@ extension DiskPersistence.Datastore.Index {
702711
newPageBlocks[insertionIndex].append(block)
703712
}
704713

705-
/// Mark the existing page as one that no longer exists
706-
newOrderedPages.append(.removed(pageID))
714+
/// If the index had data on disk, or it existed prior to the transaction, mark it as removed.
715+
/// Otherwise, simply skip the page, since we added it in a transient index.
716+
removedPages.insert(existingPage)
717+
if isPersisted || pageInfo.isExisting {
718+
newOrderedPages.append(.removed(pageID))
719+
}
707720

708721
/// Calculate how much room is left on the last page we are making, so we can finish importing the remaining blocks form the original page, creating new pages if necessary.
709722
remainingSpace = actualPageSize - newPageBlocks[newPageBlocks.count-1].encodedSize
@@ -719,7 +732,13 @@ extension DiskPersistence.Datastore.Index {
719732
}
720733
} else {
721734
/// If if doesn't, leave the page as is, and insert the rest of the new blocks as pages following this one.
722-
newOrderedPages.append(.existing(pageID))
735+
if isPersisted {
736+
/// Add the specified page as an existing page, since this is an index based on persisted data.
737+
newOrderedPages.append(.existing(pageID))
738+
} else {
739+
/// Add the specified page as is since we are working off a transient index, and would lose the fact that it may have been recently added otherwise.
740+
newOrderedPages.append(pageInfo)
741+
}
723742
newPageBlocks = entryBlocks.map { [$0] }
724743
}
725744
} else {
@@ -748,8 +767,12 @@ extension DiskPersistence.Datastore.Index {
748767
/// Note that we are guaranteed to have at least one new page by this point, since we are inserting and not replacing.
749768
let remainingSpace = actualPageSize - newPageBlocks[newPageBlocks.count - 1].encodedSize
750769
if existingPageBlocks.encodedSize <= remainingSpace {
751-
/// Mark the page we are removing accordingly
752-
newOrderedPages.append(.removed(pageID))
770+
/// If the index had data on disk, or it existed prior to the transaction, mark it as removed.
771+
/// Otherwise, simply skip the page, since we added it in a transient index.
772+
removedPages.insert(existingPage)
773+
if isPersisted || pageInfo.isExisting {
774+
newOrderedPages.append(.removed(pageID))
775+
}
753776

754777
/// Import the blocks into the last page.
755778
newPageBlocks[newPageBlocks.count - 1].append(contentsOf: existingPageBlocks)
@@ -780,8 +803,15 @@ extension DiskPersistence.Datastore.Index {
780803
newOrderedPages.append(.added(newPageID))
781804
}
782805

806+
/// Conditionally import the current page after we inserted everything.
783807
if importCurrentPage {
784-
newOrderedPages.append(.existing(pageID))
808+
if isPersisted {
809+
/// Add the specified page as an existing page, since this is an index based on persisted data.
810+
newOrderedPages.append(.existing(pageID))
811+
} else {
812+
/// Add the specified page as is since we are working off a transient index, and would lose the fact that it may have been recently added otherwise.
813+
newOrderedPages.append(pageInfo)
814+
}
785815
}
786816
}
787817
}

Sources/CodableDatastore/Persistence/Disk Persistence/Datastore/DatastoreIndexManifest.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,21 @@ extension DatastoreIndexManifest {
6868
return id
6969
}
7070
}
71+
72+
var isExisting: Bool {
73+
if case .existing = self { return true }
74+
return false
75+
}
76+
77+
var isRemoved: Bool {
78+
if case .removed = self { return true }
79+
return false
80+
}
81+
82+
var isAdded: Bool {
83+
if case .added = self { return true }
84+
return false
85+
}
7186
}
7287
}
7388

0 commit comments

Comments
 (0)