Skip to content

Commit

Permalink
Improve performance by caching keychain transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
hpique committed Oct 25, 2013
1 parent c198cc9 commit 0705b4f
Showing 1 changed file with 29 additions and 21 deletions.
50 changes: 29 additions & 21 deletions RMStore/Optional/RMStoreKeychainPersistence.m
Original file line number Diff line number Diff line change
Expand Up @@ -84,39 +84,41 @@ void RMKeychainSetValue(NSData *value, NSString *key)
return (__bridge NSData*)value;
}

@implementation RMStoreKeychainPersistence
@implementation RMStoreKeychainPersistence {
NSDictionary *_transactionsDictionary;
}

#pragma mark - RMStoreTransactionPersistor

- (void)persistTransaction:(SKPaymentTransaction*)paymentTransaction
{
SKPayment *payment = paymentTransaction.payment;
NSString *productIdentifier = payment.productIdentifier;
NSDictionary *transactions = [RMStoreKeychainPersistence transactionsDictionary];
NSDictionary *transactions = [self transactionsDictionary];
NSInteger count = [[transactions objectForKey:productIdentifier] integerValue];
count++;
NSMutableDictionary *updatedTransactions = [NSMutableDictionary dictionaryWithDictionary:transactions];
[updatedTransactions setObject:@(count) forKey:productIdentifier];
[RMStoreKeychainPersistence setTransactionsDictionary:updatedTransactions];
[self setTransactionsDictionary:updatedTransactions];
}

#pragma mark - Public

- (void)removeTransactions
{
[RMStoreKeychainPersistence setTransactionsDictionary:nil];
[self setTransactionsDictionary:nil];
}

- (BOOL)consumeProductOfIdentifier:(NSString*)productIdentifier
{
NSDictionary *transactions = [RMStoreKeychainPersistence transactionsDictionary];
NSDictionary *transactions = [self transactionsDictionary];
NSInteger count = [[transactions objectForKey:productIdentifier] integerValue];
if (count > 0)
{
count--;
NSMutableDictionary *updatedTransactions = [NSMutableDictionary dictionaryWithDictionary:transactions];
[updatedTransactions setObject:@(count) forKey:productIdentifier];
[RMStoreKeychainPersistence setTransactionsDictionary:updatedTransactions];
[self setTransactionsDictionary:updatedTransactions];
return YES;
} else {
return NO;
Expand All @@ -125,43 +127,49 @@ - (BOOL)consumeProductOfIdentifier:(NSString*)productIdentifier

- (NSInteger)countProductOfdentifier:(NSString*)productIdentifier
{
NSDictionary *transactions = [RMStoreKeychainPersistence transactionsDictionary];
NSDictionary *transactions = [self transactionsDictionary];
NSInteger count = [[transactions objectForKey:productIdentifier] integerValue];
return count;
}

- (BOOL)isPurchasedProductOfIdentifier:(NSString*)productIdentifier
{
NSDictionary *transactions = [RMStoreKeychainPersistence transactionsDictionary];
NSDictionary *transactions = [self transactionsDictionary];
return [transactions objectForKey:productIdentifier] != nil;
}

- (NSSet*)purchasedProductIdentifiers
{
NSDictionary *transactions = [RMStoreKeychainPersistence transactionsDictionary];
NSDictionary *transactions = [self transactionsDictionary];
NSArray *productIdentifiers = [transactions allKeys];
return [NSSet setWithArray:productIdentifiers];
}

#pragma mark - Private

+ (NSDictionary*)transactionsDictionary
- (NSDictionary*)transactionsDictionary
{
NSData *data = RMKeychainGetValue(RMStoreTransactionsKeychainKey);
NSDictionary *transactions;
if (data)
{
NSError *error;
transactions = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSAssert(!error, [error localizedDescription]);
} else {
transactions = [NSDictionary dictionary];
if (_transactionsDictionary)

This comment has been minimized.

Copy link
@koedal

koedal Oct 28, 2013

In order to cache, shouldn't this read:
if (!_transactionsDictionary)

This comment has been minimized.

Copy link
@hpique

hpique Oct 28, 2013

Author Member

Certainly looks like it. I wonder how this passed the unit tests. Will fix it ASAP. Thanks @koedal.

This comment has been minimized.

Copy link
@hpique

hpique Oct 28, 2013

Author Member

Fixed in 1648cf7. Will add a unit test that would have failed.

This comment has been minimized.

Copy link
@koedal

koedal Oct 28, 2013

Thanks for the fast fix!

This comment has been minimized.

Copy link
@hpique

hpique Oct 28, 2013

Author Member

Unit tests updated to fail if the bug returns (c84cafe). Apologies if this caused any inconvenience.

{ // Reading the keychain is slow so we cache its values in memory
NSData *data = RMKeychainGetValue(RMStoreTransactionsKeychainKey);
NSDictionary *transactions;
if (data)
{
NSError *error;
transactions = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSAssert(!error, [error localizedDescription]);
} else {
transactions = [NSDictionary dictionary];
}
_transactionsDictionary = transactions;
}
return transactions;
return _transactionsDictionary;

}

+ (void)setTransactionsDictionary:(NSDictionary*)dictionary
- (void)setTransactionsDictionary:(NSDictionary*)dictionary
{
_transactionsDictionary = dictionary;
NSData *data = nil;
if (dictionary)
{
Expand Down

0 comments on commit 0705b4f

Please sign in to comment.