Skip to content

Commit db3f015

Browse files
committed
Concurrent transaction queue, serialize access to _transactions MutableDictionary.
1 parent 69fb950 commit db3f015

File tree

2 files changed

+26
-14
lines changed

2 files changed

+26
-14
lines changed

ios/Firestack/FirestackDatabase.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
@property NSMutableDictionary *dbReferences;
2121
@property NSMutableDictionary *transactions;
22+
@property dispatch_queue_t transactionQueue;
2223

2324
@end
2425

ios/Firestack/FirestackDatabase.m

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ @interface FirestackDBReference : NSObject
2222
@property FIRDatabaseHandle childMovedHandler;
2323
@property FIRDatabaseHandle childValueHandler;
2424
+ (NSDictionary *) snapshotToDict:(FIRDataSnapshot *) snapshot;
25+
2526
@end
2627

2728
@implementation FirestackDBReference
@@ -366,6 +367,7 @@ - (id) init
366367
if (self != nil) {
367368
_dbReferences = [[NSMutableDictionary alloc] init];
368369
_transactions = [[NSMutableDictionary alloc] init];
370+
_transactionQueue = dispatch_queue_create("com.fullstackreact.react-native-firestack", DISPATCH_QUEUE_CONCURRENT);
369371
}
370372
return self;
371373
}
@@ -462,24 +464,29 @@ - (id) init
462464
applyLocally:(BOOL) applyLocally
463465
onComplete:(RCTResponseSenderBlock) onComplete)
464466
{
465-
NSMutableDictionary *transactionState = [NSMutableDictionary new];
466-
[_transactions setValue:transactionState forKey:identifier];
467-
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
468-
[transactionState setObject:sema forKey:@"semaphore"];
469-
470-
FIRDatabaseReference *ref = [self getPathRef:path];
471-
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
467+
dispatch_async(_transactionQueue, ^{
468+
NSMutableDictionary *transactionState = [NSMutableDictionary new];
469+
470+
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
471+
[transactionState setObject:sema forKey:@"semaphore"];
472+
473+
FIRDatabaseReference *ref = [self getPathRef:path];
472474
[ref runTransactionBlock:^FIRTransactionResult * _Nonnull(FIRMutableData * _Nonnull currentData) {
473-
[self sendEventWithName:DATABASE_TRANSACTION_EVENT
474-
body:@{
475-
@"id": identifier,
476-
@"originalValue": currentData.value
477-
}];
475+
dispatch_barrier_async(_transactionQueue, ^{
476+
[_transactions setValue:transactionState forKey:identifier];
477+
[self sendEventWithName:DATABASE_TRANSACTION_EVENT
478+
body:@{
479+
@"id": identifier,
480+
@"originalValue": currentData.value
481+
}];
482+
});
478483
// Wait for the event handler to call tryCommitTransaction
479484
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
480485
BOOL abort = [transactionState valueForKey:@"abort"];
481486
id value = [transactionState valueForKey:@"value"];
482-
[_transactions removeObjectForKey:identifier];
487+
dispatch_barrier_async(_transactionQueue, ^{
488+
[_transactions removeObjectForKey:identifier];
489+
});
483490
if (abort) {
484491
return [FIRTransactionResult abort];
485492
} else {
@@ -510,9 +517,13 @@ - (id) init
510517
withData:(NSDictionary *) data
511518
orAbort:(BOOL) abort)
512519
{
513-
NSMutableDictionary *transactionState = [_transactions valueForKey:identifier];
520+
__block NSMutableDictionary *transactionState;
521+
dispatch_sync(_transactionQueue, ^{
522+
transactionState = [_transactions objectForKey: identifier];
523+
});
514524
if (!transactionState) {
515525
NSLog(@"tryCommitTransaction for unknown ID %@", identifier);
526+
return;
516527
}
517528
dispatch_semaphore_t sema = [transactionState valueForKey:@"semaphore"];
518529
if (abort) {

0 commit comments

Comments
 (0)