diff options
author | Greg Soltis <gsoltis@google.com> | 2018-03-22 17:31:16 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-22 17:31:16 -0700 |
commit | 352b790b6e292c0d921ad0231352d767fde53758 (patch) | |
tree | 75a8c78fc35f846eb1f763ea3b664d6800850e2b /Firestore/Example | |
parent | c1c9fecb6f7e057817afca9f1e32d2abba3ecfe8 (diff) |
Switch FSTLevelDBQueryCache to use transactions (#942)
* Start work on leveldb transactions
* Style
* Working API. Not plumbed in yet
* Move files into correct place
* Wrangling file locations and associations
* Tests pass
* Add some comments
* style
* Fix copyright
* Rewrite iterator internals to handle deletion-while-iterating. Also add tests for same
* Switch to strings instead of slices
* Style
* More style fixes
* Start switching writegroup over
* Swap out write group tracking for transaction usage
* Style
* Response to feedback before updating docs
* Style
* Add comment
* Initialize version_
* Satisfy the linter
* Start switching writegroup over
* Swap out write group tracking for transaction usage
* Style
* Checkpoint before implementing BatchDescription
* Style
* Initial plumbing for leveldb local parts
* Add model::BatchId
* Port leveldb_key.{h,cc}
* Add string StartsWith
* Add leveldb_key_test.cc to the project
* Revert back to using leveldb::Slice for read/describe
These operations universally operate on keys obtained from leveldb so
it's actually unhelpful to force all the callers to make
absl::string_views from them.
* Everything passing
* Drop unused function
* Style
* STart work on reads
* Swap reads in queryCache to use transactions
* Fix up tests of querycache
* Drop commented out code
* Cleanup
* Style
* Fix up for passing tests
* style
* Renaming
* Style
* Start work on ToString for transactions
* Add ToString() method to LevelDbTransaction
* Style
* lint
* Fix includes, drop runTransaction
* current_transaction -> currentTransaction
* LevelDbTransaction::NewIterator now returns a unique_ptr
* Style
* Revert addition of util::StartsWith
* Add log line
* Style
* Add log line
* Style
* Add debug log line for commits, drop unused BatchDescription
* Fix an include, but mostly try to trigger a travis build
Diffstat (limited to 'Firestore/Example')
3 files changed, 89 insertions, 85 deletions
diff --git a/Firestore/Example/Tests/Local/FSTLevelDBMigrationsTests.mm b/Firestore/Example/Tests/Local/FSTLevelDBMigrationsTests.mm index 822e3ca..4f0332e 100644 --- a/Firestore/Example/Tests/Local/FSTLevelDBMigrationsTests.mm +++ b/Firestore/Example/Tests/Local/FSTLevelDBMigrationsTests.mm @@ -15,13 +15,13 @@ */ #import <XCTest/XCTest.h> -#include <leveldb/db.h> #import "Firestore/Protos/objc/firestore/local/Target.pbobjc.h" #import "Firestore/Source/Local/FSTLevelDB.h" #import "Firestore/Source/Local/FSTLevelDBKey.h" #import "Firestore/Source/Local/FSTLevelDBMigrations.h" #import "Firestore/Source/Local/FSTLevelDBQueryCache.h" +#include "leveldb/db.h" #include "Firestore/core/src/firebase/firestore/util/ordered_code.h" diff --git a/Firestore/Example/Tests/Local/FSTLevelDBTransactionTests.mm b/Firestore/Example/Tests/Local/FSTLevelDBTransactionTests.mm index 2a1efb0..c959b4f 100644 --- a/Firestore/Example/Tests/Local/FSTLevelDBTransactionTests.mm +++ b/Firestore/Example/Tests/Local/FSTLevelDBTransactionTests.mm @@ -62,7 +62,7 @@ using firebase::firestore::local::LevelDbTransaction; std::string key = "key1"; transaction.Put(key, "value"); - std::unique_ptr<LevelDbTransaction::Iterator> iter(transaction.NewIterator()); + auto iter = transaction.NewIterator(); iter->Seek(key); XCTAssertEqual(key, iter->key()); iter->Next(); @@ -212,7 +212,7 @@ using firebase::firestore::local::LevelDbTransaction; transaction.Put("key_" + std::to_string(i), "value_" + std::to_string(i)); } - std::unique_ptr<LevelDbTransaction::Iterator> it(transaction.NewIterator()); + auto it = transaction.NewIterator(); it->Seek("key_0"); for (int i = 0; i < 4; ++i) { XCTAssertTrue(it->Valid()); @@ -234,7 +234,7 @@ using firebase::firestore::local::LevelDbTransaction; // Create a transaction, iterate, deleting key_0. Verify we still iterate key_1. LevelDbTransaction transaction(_db.get()); - std::unique_ptr<LevelDbTransaction::Iterator> it(transaction.NewIterator()); + auto it = transaction.NewIterator(); it->Seek("key_0"); XCTAssertTrue(it->Valid()); XCTAssertEqual("key_0", it->key()); @@ -256,7 +256,7 @@ using firebase::firestore::local::LevelDbTransaction; // Create a transaction, iterate to key_1, delete key_2. Verify we still iterate key_3. LevelDbTransaction transaction(_db.get()); - std::unique_ptr<LevelDbTransaction::Iterator> it(transaction.NewIterator()); + auto it = transaction.NewIterator(); it->Seek("key_0"); XCTAssertTrue(it->Valid()); XCTAssertEqual("key_0", it->key()); diff --git a/Firestore/Example/Tests/Local/FSTQueryCacheTests.mm b/Firestore/Example/Tests/Local/FSTQueryCacheTests.mm index 0618e9c..6ef927d 100644 --- a/Firestore/Example/Tests/Local/FSTQueryCacheTests.mm +++ b/Firestore/Example/Tests/Local/FSTQueryCacheTests.mm @@ -56,24 +56,29 @@ NS_ASSUME_NONNULL_BEGIN - (void)testReadQueryNotInCache { if ([self isTestBaseClass]) return; + FSTWriteGroup *group = [self.persistence startGroupWithAction:@"ReadQueryNotInCache"]; XCTAssertNil([self.queryCache queryDataForQuery:_queryRooms]); + [self.persistence commitGroup:group]; } - (void)testSetAndReadAQuery { if ([self isTestBaseClass]) return; + FSTWriteGroup *group = [self.persistence startGroupWithAction:@"SetAndReadQuery"]; FSTQueryData *queryData = [self queryDataWithQuery:_queryRooms]; - [self addQueryData:queryData]; + [self.queryCache addQueryData:queryData group:group]; FSTQueryData *result = [self.queryCache queryDataForQuery:_queryRooms]; XCTAssertEqualObjects(result.query, queryData.query); XCTAssertEqual(result.targetID, queryData.targetID); XCTAssertEqualObjects(result.resumeToken, queryData.resumeToken); + [self.persistence commitGroup:group]; } - (void)testCanonicalIDCollision { if ([self isTestBaseClass]) return; + FSTWriteGroup *group = [self.persistence startGroupWithAction:@"CanonicalIDCollision"]; // Type information is currently lost in our canonicalID implementations so this currently an // easy way to force colliding canonicalIDs FSTQuery *q1 = [FSTTestQuery("a") queryByAddingFilter:FSTTestFilter("foo", @"==", @(1))]; @@ -81,136 +86,151 @@ NS_ASSUME_NONNULL_BEGIN XCTAssertEqualObjects(q1.canonicalID, q2.canonicalID); FSTQueryData *data1 = [self queryDataWithQuery:q1]; - [self addQueryData:data1]; + [self.queryCache addQueryData:data1 group:group]; // Using the other query should not return the query cache entry despite equal canonicalIDs. XCTAssertNil([self.queryCache queryDataForQuery:q2]); XCTAssertEqualObjects([self.queryCache queryDataForQuery:q1], data1); FSTQueryData *data2 = [self queryDataWithQuery:q2]; - [self addQueryData:data2]; + [self.queryCache addQueryData:data2 group:group]; XCTAssertEqual([self.queryCache count], 2); XCTAssertEqualObjects([self.queryCache queryDataForQuery:q1], data1); XCTAssertEqualObjects([self.queryCache queryDataForQuery:q2], data2); - [self removeQueryData:data1]; + [self.queryCache removeQueryData:data1 group:group]; XCTAssertNil([self.queryCache queryDataForQuery:q1]); XCTAssertEqualObjects([self.queryCache queryDataForQuery:q2], data2); XCTAssertEqual([self.queryCache count], 1); - [self removeQueryData:data2]; + [self.queryCache removeQueryData:data2 group:group]; XCTAssertNil([self.queryCache queryDataForQuery:q1]); XCTAssertNil([self.queryCache queryDataForQuery:q2]); XCTAssertEqual([self.queryCache count], 0); + [self.persistence commitGroup:group]; } - (void)testSetQueryToNewValue { if ([self isTestBaseClass]) return; + FSTWriteGroup *group = [self.persistence startGroupWithAction:@"SetQueryToNewValue"]; FSTQueryData *queryData1 = [self queryDataWithQuery:_queryRooms targetID:1 listenSequenceNumber:10 version:1]; - [self addQueryData:queryData1]; + [self.queryCache addQueryData:queryData1 group:group]; FSTQueryData *queryData2 = [self queryDataWithQuery:_queryRooms targetID:1 listenSequenceNumber:10 version:2]; - [self addQueryData:queryData2]; + [self.queryCache addQueryData:queryData2 group:group]; FSTQueryData *result = [self.queryCache queryDataForQuery:_queryRooms]; XCTAssertNotEqualObjects(queryData2.resumeToken, queryData1.resumeToken); XCTAssertNotEqualObjects(queryData2.snapshotVersion, queryData1.snapshotVersion); XCTAssertEqualObjects(result.resumeToken, queryData2.resumeToken); XCTAssertEqualObjects(result.snapshotVersion, queryData2.snapshotVersion); + [self.persistence commitGroup:group]; } - (void)testRemoveQuery { if ([self isTestBaseClass]) return; + FSTWriteGroup *group = [self.persistence startGroupWithAction:@"RemoveQuery"]; FSTQueryData *queryData1 = [self queryDataWithQuery:_queryRooms]; - [self addQueryData:queryData1]; + [self.queryCache addQueryData:queryData1 group:group]; - [self removeQueryData:queryData1]; + [self.queryCache removeQueryData:queryData1 group:group]; FSTQueryData *result = [self.queryCache queryDataForQuery:_queryRooms]; XCTAssertNil(result); + [self.persistence commitGroup:group]; } - (void)testRemoveNonExistentQuery { if ([self isTestBaseClass]) return; + FSTWriteGroup *group = [self.persistence startGroupWithAction:@"RemoveNonExistentQuery"]; FSTQueryData *queryData = [self queryDataWithQuery:_queryRooms]; // no-op, but make sure it doesn't throw. - XCTAssertNoThrow([self removeQueryData:queryData]); + XCTAssertNoThrow([self.queryCache removeQueryData:queryData group:group]); + [self.persistence commitGroup:group]; } - (void)testRemoveQueryRemovesMatchingKeysToo { if ([self isTestBaseClass]) return; + FSTWriteGroup *group = + [self.persistence startGroupWithAction:@"RemoveQueryRemovesMatchingKeysToo"]; FSTQueryData *rooms = [self queryDataWithQuery:_queryRooms]; - [self addQueryData:rooms]; + [self.queryCache addQueryData:rooms group:group]; FSTDocumentKey *key1 = FSTTestDocKey(@"rooms/foo"); FSTDocumentKey *key2 = FSTTestDocKey(@"rooms/bar"); - [self addMatchingKey:key1 forTargetID:rooms.targetID]; - [self addMatchingKey:key2 forTargetID:rooms.targetID]; + [self addMatchingKey:key1 forTargetID:rooms.targetID group:group]; + [self addMatchingKey:key2 forTargetID:rooms.targetID group:group]; XCTAssertTrue([self.queryCache containsKey:key1]); XCTAssertTrue([self.queryCache containsKey:key2]); - [self removeQueryData:rooms]; + [self.queryCache removeQueryData:rooms group:group]; XCTAssertFalse([self.queryCache containsKey:key1]); XCTAssertFalse([self.queryCache containsKey:key2]); + [self.persistence commitGroup:group]; } - (void)testAddOrRemoveMatchingKeys { if ([self isTestBaseClass]) return; + FSTWriteGroup *group = [self.persistence startGroupWithAction:@"AddOrRemoveMatchingKeys"]; FSTDocumentKey *key = FSTTestDocKey(@"foo/bar"); XCTAssertFalse([self.queryCache containsKey:key]); - [self addMatchingKey:key forTargetID:1]; + [self addMatchingKey:key forTargetID:1 group:group]; XCTAssertTrue([self.queryCache containsKey:key]); - [self addMatchingKey:key forTargetID:2]; + [self addMatchingKey:key forTargetID:2 group:group]; XCTAssertTrue([self.queryCache containsKey:key]); - [self removeMatchingKey:key forTargetID:1]; + [self removeMatchingKey:key forTargetID:1 group:group]; XCTAssertTrue([self.queryCache containsKey:key]); - [self removeMatchingKey:key forTargetID:2]; + [self removeMatchingKey:key forTargetID:2 group:group]; XCTAssertFalse([self.queryCache containsKey:key]); + [self.persistence commitGroup:group]; } - (void)testRemoveMatchingKeysForTargetID { if ([self isTestBaseClass]) return; + FSTWriteGroup *group = [self.persistence startGroupWithAction:@"RemoveMatchingKeysForTargetID"]; FSTDocumentKey *key1 = FSTTestDocKey(@"foo/bar"); FSTDocumentKey *key2 = FSTTestDocKey(@"foo/baz"); FSTDocumentKey *key3 = FSTTestDocKey(@"foo/blah"); - [self addMatchingKey:key1 forTargetID:1]; - [self addMatchingKey:key2 forTargetID:1]; - [self addMatchingKey:key3 forTargetID:2]; + [self addMatchingKey:key1 forTargetID:1 group:group]; + [self addMatchingKey:key2 forTargetID:1 group:group]; + [self addMatchingKey:key3 forTargetID:2 group:group]; XCTAssertTrue([self.queryCache containsKey:key1]); XCTAssertTrue([self.queryCache containsKey:key2]); XCTAssertTrue([self.queryCache containsKey:key3]); - [self removeMatchingKeysForTargetID:1]; + [self.queryCache removeMatchingKeysForTargetID:1 group:group]; XCTAssertFalse([self.queryCache containsKey:key1]); XCTAssertFalse([self.queryCache containsKey:key2]); XCTAssertTrue([self.queryCache containsKey:key3]); - [self removeMatchingKeysForTargetID:2]; + [self.queryCache removeMatchingKeysForTargetID:2 group:group]; XCTAssertFalse([self.queryCache containsKey:key1]); XCTAssertFalse([self.queryCache containsKey:key2]); XCTAssertFalse([self.queryCache containsKey:key3]); + [self.persistence commitGroup:group]; } - (void)testRemoveEmitsGarbageEvents { if ([self isTestBaseClass]) return; + FSTWriteGroup *group = [self.persistence startGroupWithAction:@"RemoveEmitsGarbageEvents"]; FSTEagerGarbageCollector *garbageCollector = [[FSTEagerGarbageCollector alloc] init]; [garbageCollector addGarbageSource:self.queryCache]; FSTAssertEqualSets([garbageCollector collectGarbage], @[]); @@ -218,65 +238,69 @@ NS_ASSUME_NONNULL_BEGIN FSTQueryData *rooms = [self queryDataWithQuery:FSTTestQuery("rooms")]; FSTDocumentKey *room1 = FSTTestDocKey(@"rooms/bar"); FSTDocumentKey *room2 = FSTTestDocKey(@"rooms/foo"); - [self addQueryData:rooms]; - [self addMatchingKey:room1 forTargetID:rooms.targetID]; - [self addMatchingKey:room2 forTargetID:rooms.targetID]; + [self.queryCache addQueryData:rooms group:group]; + [self addMatchingKey:room1 forTargetID:rooms.targetID group:group]; + [self addMatchingKey:room2 forTargetID:rooms.targetID group:group]; FSTQueryData *halls = [self queryDataWithQuery:FSTTestQuery("halls")]; FSTDocumentKey *hall1 = FSTTestDocKey(@"halls/bar"); FSTDocumentKey *hall2 = FSTTestDocKey(@"halls/foo"); - [self addQueryData:halls]; - [self addMatchingKey:hall1 forTargetID:halls.targetID]; - [self addMatchingKey:hall2 forTargetID:halls.targetID]; + [self.queryCache addQueryData:halls group:group]; + [self addMatchingKey:hall1 forTargetID:halls.targetID group:group]; + [self addMatchingKey:hall2 forTargetID:halls.targetID group:group]; FSTAssertEqualSets([garbageCollector collectGarbage], @[]); - [self removeMatchingKey:room1 forTargetID:rooms.targetID]; + [self removeMatchingKey:room1 forTargetID:rooms.targetID group:group]; FSTAssertEqualSets([garbageCollector collectGarbage], @[ room1 ]); - [self removeQueryData:rooms]; + [self.queryCache removeQueryData:rooms group:group]; FSTAssertEqualSets([garbageCollector collectGarbage], @[ room2 ]); - [self removeMatchingKeysForTargetID:halls.targetID]; + [self.queryCache removeMatchingKeysForTargetID:halls.targetID group:group]; FSTAssertEqualSets([garbageCollector collectGarbage], (@[ hall1, hall2 ])); + [self.persistence commitGroup:group]; } - (void)testMatchingKeysForTargetID { if ([self isTestBaseClass]) return; + FSTWriteGroup *group = [self.persistence startGroupWithAction:@"MatchingKeysForTargetID"]; FSTDocumentKey *key1 = FSTTestDocKey(@"foo/bar"); FSTDocumentKey *key2 = FSTTestDocKey(@"foo/baz"); FSTDocumentKey *key3 = FSTTestDocKey(@"foo/blah"); - [self addMatchingKey:key1 forTargetID:1]; - [self addMatchingKey:key2 forTargetID:1]; - [self addMatchingKey:key3 forTargetID:2]; + [self addMatchingKey:key1 forTargetID:1 group:group]; + [self addMatchingKey:key2 forTargetID:1 group:group]; + [self addMatchingKey:key3 forTargetID:2 group:group]; FSTAssertEqualSets([self.queryCache matchingKeysForTargetID:1], (@[ key1, key2 ])); FSTAssertEqualSets([self.queryCache matchingKeysForTargetID:2], @[ key3 ]); - [self addMatchingKey:key1 forTargetID:2]; + [self addMatchingKey:key1 forTargetID:2 group:group]; FSTAssertEqualSets([self.queryCache matchingKeysForTargetID:1], (@[ key1, key2 ])); FSTAssertEqualSets([self.queryCache matchingKeysForTargetID:2], (@[ key1, key3 ])); + [self.persistence commitGroup:group]; } - (void)testHighestListenSequenceNumber { if ([self isTestBaseClass]) return; + FSTWriteGroup *group = [self.persistence startGroupWithAction:@"HighestListenSequenceNumber"]; FSTQueryData *query1 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery("rooms") targetID:1 listenSequenceNumber:10 purpose:FSTQueryPurposeListen]; - [self addQueryData:query1]; + [self.queryCache addQueryData:query1 group:group]; FSTQueryData *query2 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery("halls") targetID:2 listenSequenceNumber:20 purpose:FSTQueryPurposeListen]; - [self addQueryData:query2]; + [self.queryCache addQueryData:query2 group:group]; XCTAssertEqual([self.queryCache highestListenSequenceNumber], 20); // TargetIDs never come down. - [self removeQueryData:query2]; + [self.queryCache removeQueryData:query2 group:group]; XCTAssertEqual([self.queryCache highestListenSequenceNumber], 20); // A query with an empty result set still counts. @@ -284,14 +308,15 @@ NS_ASSUME_NONNULL_BEGIN targetID:42 listenSequenceNumber:100 purpose:FSTQueryPurposeListen]; - [self addQueryData:query3]; + [self.queryCache addQueryData:query3 group:group]; XCTAssertEqual([self.queryCache highestListenSequenceNumber], 100); - [self removeQueryData:query1]; + [self.queryCache removeQueryData:query1 group:group]; XCTAssertEqual([self.queryCache highestListenSequenceNumber], 100); - [self removeQueryData:query3]; + [self.queryCache removeQueryData:query3 group:group]; XCTAssertEqual([self.queryCache highestListenSequenceNumber], 100); + [self.persistence commitGroup:group]; // Verify that the highestTargetID even survives restarts. [self.queryCache shutdown]; @@ -303,6 +328,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)testHighestTargetID { if ([self isTestBaseClass]) return; + FSTWriteGroup *group = [self.persistence startGroupWithAction:@"RemoveMatchingKeysForTargetID"]; XCTAssertEqual([self.queryCache highestTargetID], 0); FSTQueryData *query1 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery("rooms") @@ -311,21 +337,21 @@ NS_ASSUME_NONNULL_BEGIN purpose:FSTQueryPurposeListen]; FSTDocumentKey *key1 = FSTTestDocKey(@"rooms/bar"); FSTDocumentKey *key2 = FSTTestDocKey(@"rooms/foo"); - [self addQueryData:query1]; - [self addMatchingKey:key1 forTargetID:1]; - [self addMatchingKey:key2 forTargetID:1]; + [self.queryCache addQueryData:query1 group:group]; + [self addMatchingKey:key1 forTargetID:1 group:group]; + [self addMatchingKey:key2 forTargetID:1 group:group]; FSTQueryData *query2 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery("halls") targetID:2 listenSequenceNumber:20 purpose:FSTQueryPurposeListen]; FSTDocumentKey *key3 = FSTTestDocKey(@"halls/foo"); - [self addQueryData:query2]; - [self addMatchingKey:key3 forTargetID:2]; + [self.queryCache addQueryData:query2 group:group]; + [self addMatchingKey:key3 forTargetID:2 group:group]; XCTAssertEqual([self.queryCache highestTargetID], 2); // TargetIDs never come down. - [self removeQueryData:query2]; + [self.queryCache removeQueryData:query2 group:group]; XCTAssertEqual([self.queryCache highestTargetID], 2); // A query with an empty result set still counts. @@ -333,15 +359,15 @@ NS_ASSUME_NONNULL_BEGIN targetID:42 listenSequenceNumber:100 purpose:FSTQueryPurposeListen]; - [self addQueryData:query3]; + [self.queryCache addQueryData:query3 group:group]; XCTAssertEqual([self.queryCache highestTargetID], 42); - [self removeQueryData:query1]; + [self.queryCache removeQueryData:query1 group:group]; XCTAssertEqual([self.queryCache highestTargetID], 42); - [self removeQueryData:query3]; + [self.queryCache removeQueryData:query3 group:group]; XCTAssertEqual([self.queryCache highestTargetID], 42); - + [self.persistence commitGroup:group]; // Verify that the highestTargetID even survives restarts. [self.queryCache shutdown]; self.queryCache = [self.persistence queryCache]; @@ -393,42 +419,20 @@ NS_ASSUME_NONNULL_BEGIN resumeToken:resumeToken]; } -/** Adds the given query data to the queryCache under test, committing immediately. */ -- (void)addQueryData:(FSTQueryData *)queryData { - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"addQueryData"]; - [self.queryCache addQueryData:queryData group:group]; - [self.persistence commitGroup:group]; -} - -/** Removes the given query data from the queryCache under test, committing immediately. */ -- (void)removeQueryData:(FSTQueryData *)queryData { - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"removeQueryData"]; - [self.queryCache removeQueryData:queryData group:group]; - [self.persistence commitGroup:group]; -} - -- (void)addMatchingKey:(FSTDocumentKey *)key forTargetID:(FSTTargetID)targetID { +- (void)addMatchingKey:(FSTDocumentKey *)key + forTargetID:(FSTTargetID)targetID + group:(FSTWriteGroup *)group { FSTDocumentKeySet *keys = [FSTDocumentKeySet keySet]; keys = [keys setByAddingObject:key]; - - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"addMatchingKeys"]; [self.queryCache addMatchingKeys:keys forTargetID:targetID group:group]; - [self.persistence commitGroup:group]; } -- (void)removeMatchingKey:(FSTDocumentKey *)key forTargetID:(FSTTargetID)targetID { +- (void)removeMatchingKey:(FSTDocumentKey *)key + forTargetID:(FSTTargetID)targetID + group:(FSTWriteGroup *)group { FSTDocumentKeySet *keys = [FSTDocumentKeySet keySet]; keys = [keys setByAddingObject:key]; - - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"removeMatchingKeys"]; [self.queryCache removeMatchingKeys:keys forTargetID:targetID group:group]; - [self.persistence commitGroup:group]; -} - -- (void)removeMatchingKeysForTargetID:(FSTTargetID)targetID { - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"removeMatchingKeysForTargetID"]; - [self.queryCache removeMatchingKeysForTargetID:targetID group:group]; - [self.persistence commitGroup:group]; } @end |