diff --git a/Sources/Document/Document.swift b/Sources/Document/Document.swift index 40826b09..07f99fdc 100644 --- a/Sources/Document/Document.swift +++ b/Sources/Document/Document.swift @@ -17,6 +17,18 @@ import Combine import Foundation +/** + * `DocumentOptions` are the options to create a new document. + * + * @public + */ +public struct DocumentOptions { + /** + * `disableGC` disables garbage collection if true. + */ + var disableGC: Bool +} + /** * `DocumentStatus` represents the status of the document. */ @@ -59,6 +71,7 @@ public actor Document { private let key: DocumentKey private(set) var status: DocumentStatus + private let opts: DocumentOptions private var changeID: ChangeID var checkpoint: Checkpoint private var localChanges: [Change] @@ -81,8 +94,13 @@ public actor Document { private var presences: [ActorID: StringValueTypeDictionary] public init(key: String) { + self.init(key: key, opts: DocumentOptions(disableGC: false)) + } + + public init(key: String, opts: DocumentOptions) { self.key = key self.status = .detached + self.opts = opts self.root = CRDTRoot() self.changeID = ChangeID.initial self.checkpoint = Checkpoint.initial @@ -300,6 +318,10 @@ public actor Document { */ @discardableResult func garbageCollect(lessThanOrEqualTo ticket: TimeTicket) -> Int { + if self.opts.disableGC { + return 0 + } + if let clone = self.clone { clone.root.garbageCollect(lessThanOrEqualTo: ticket) } diff --git a/Tests/Integration/GCTests.swift b/Tests/Integration/GCTests.swift index 27e2aa6e..71badbce 100644 --- a/Tests/Integration/GCTests.swift +++ b/Tests/Integration/GCTests.swift @@ -66,6 +66,33 @@ class GCTests: XCTestCase { XCTAssertEqual(0, len) } + func test_disable_GC_test() async throws { + let doc = Document(key: "test-doc", opts: DocumentOptions(disableGC: true)) + + try await doc.update({ root, _ in + root["1"] = Int64(1) + root["2"] = [Int64(1), Int64(2), Int64(3)] + root["3"] = Int64(3) + }, "set 1, 2, 3") + + var result = await doc.toSortedJSON() + XCTAssertEqual("{\"1\":1,\"2\":[1,2,3],\"3\":3}", result) + + try await doc.update({ root, _ in + root.remove(key: "2") + }, "deletes 2") + + result = await doc.toSortedJSON() + XCTAssertEqual("{\"1\":1,\"3\":3}", result) + + var len = await doc.getGarbageLength() + XCTAssertEqual(4, len) + len = await doc.garbageCollect(lessThanOrEqualTo: TimeTicket.max) + XCTAssertEqual(0, len) + len = await doc.getGarbageLength() + XCTAssertEqual(4, len) + } + func test_garbage_collection_test2() async throws { let size = 10000 let doc = Document(key: "test-doc")