Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to set an object level TTL #209

Merged
merged 39 commits into from
May 11, 2018
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
a08b66c
Add new `ageLimit` setters in PINCaching protocol
mjlazar Dec 5, 2017
3d7714e
Implement `ageLimit` methods in PINDiskCache
mjlazar Dec 5, 2017
d1c796a
Implement `ageLimit` methods in PINMemoryCache
mjlazar Dec 5, 2017
f7d6d3c
Implement `ageLimit` methods in PINCache
mjlazar Dec 5, 2017
336d401
Honor `ageLimit` (at both cache and object level) in -[PINDiskCache c…
mjlazar Dec 5, 2017
6be8d22
Honor `ageLimit` (at both cache and object level) in -[PINDiskCache c…
mjlazar Dec 5, 2017
c2dfcd6
Merge branch 'object-level-ttl-override' of github.com:mjlazar/PINCac…
mjlazar Dec 5, 2017
4b05c88
Update CHANGELOG
mjlazar Dec 16, 2017
0d4e71d
Add new NSDate category for swizzling +[NSDate date] in unit tests
mjlazar Feb 16, 2018
d4d7640
Change memory and disk caches to use +[NDate date] instead of -[NSDat…
mjlazar Feb 16, 2018
b4b7ac2
Add unit tests for object-level TTLs
mjlazar Feb 16, 2018
171de47
Update header documentation regarding object-level age limits
mjlazar Feb 16, 2018
723c326
Clear previously set object age limits if setting to zero
mjlazar Feb 16, 2018
06e331c
Add assertions to ttlCache is set to YES if object-level age limits a…
mjlazar Feb 16, 2018
3895432
Update header documentation to describe behavior of overridden object…
mjlazar Feb 16, 2018
a4466b6
Remove `hasAgeLimit` logic
mjlazar Feb 17, 2018
c762a84
Misc cleanup
mjlazar Feb 17, 2018
fd103ca
Handle failure on extended attribute read
mjlazar Feb 17, 2018
fb7694b
Make sure trim methods do not remove objects with overridden age limits
mjlazar Feb 19, 2018
e504b0b
New methods to remove expired objects from cache
mjlazar Feb 19, 2018
24ea58a
Remove expired objects from disk cache on initialization if any objec…
mjlazar Feb 19, 2018
f539d78
Remove expired objects from memory cache on memory warning
mjlazar Feb 19, 2018
a27d755
Fix expiration logic
mjlazar Feb 19, 2018
4b383a5
Add unit test for removeExpiredObjects
mjlazar Feb 19, 2018
662a7cb
Remove assert in -setObject:...
mjlazar Feb 23, 2018
7fa42e3
Call async version of -removeExpiredObjects in -initializeDiskProperties
mjlazar Feb 23, 2018
9c3b33b
Tweaks
mjlazar Feb 23, 2018
7d88344
Merge branch 'master' into object-level-ttl-override
garrettmoon Feb 23, 2018
92e1d59
Fix warnings
mjlazar Feb 24, 2018
71b7fb9
Make ttlCache a readonly property
mjlazar Feb 25, 2018
2d0ae4b
Changes to address feedback from @garrettmoon
mjlazar Mar 17, 2018
6a34a58
Merge branch 'master' into object-level-ttl-override
mjlazar Mar 17, 2018
a47eff1
Merge branch 'master' into object-level-ttl-override
garrettmoon Mar 27, 2018
b5a6640
Changes to address @garrettmoon's feedback
mjlazar Apr 16, 2018
fab908f
Fix indents.
mjlazar Apr 16, 2018
f7216ed
Merge branch 'master' into object-level-ttl-override
mjlazar Apr 19, 2018
60c83aa
Adding additional tests
mjlazar May 8, 2018
2655498
Fix race condition in unit tests
mjlazar May 9, 2018
871f503
Update CHANGELOG
mjlazar May 9, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions PINCache.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
6928EED31E4160EE00B5D975 /* PINCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = 6928EED21E4160EE00B5D975 /* PINCaching.h */; settings = {ATTRIBUTES = (Public, ); }; };
6928EED41E4160FE00B5D975 /* PINCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = 6928EED21E4160EE00B5D975 /* PINCaching.h */; settings = {ATTRIBUTES = (Public, ); }; };
6928EED51E41610700B5D975 /* PINCaching.h in Headers */ = {isa = PBXBuildFile; fileRef = 6928EED21E4160EE00B5D975 /* PINCaching.h */; settings = {ATTRIBUTES = (Public, ); }; };
C30EE1F520373D1900D78CB9 /* NSDate+PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C30EE1EA203717DE00D78CB9 /* NSDate+PINCacheTests.m */; };
C30EE1F620373D1A00D78CB9 /* NSDate+PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C30EE1EA203717DE00D78CB9 /* NSDate+PINCacheTests.m */; };
C30EE1F720373D1B00D78CB9 /* NSDate+PINCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C30EE1EA203717DE00D78CB9 /* NSDate+PINCacheTests.m */; };
CC0105DF1E271A5C00890935 /* PINCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC0105B11E271A1600890935 /* PINCache.framework */; };
CC0105EE1E271A6400890935 /* PINCache.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC0105C11E271A4000890935 /* PINCache.framework */; };
CC01060E1E271A9500890935 /* PINCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CC0106061E271A9000890935 /* PINCache.m */; };
Expand Down Expand Up @@ -172,6 +175,8 @@
6818C2901E564C1100875DB7 /* PINOperation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = PINOperation.xcodeproj; path = Carthage/Checkouts/PINOperation/PINOperation.xcodeproj; sourceTree = "<group>"; };
68A0FBFF1E4D3282000B552D /* PINCacheMacros.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PINCacheMacros.h; sourceTree = "<group>"; };
6928EED21E4160EE00B5D975 /* PINCaching.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINCaching.h; sourceTree = "<group>"; };
C30EE1E9203717DE00D78CB9 /* NSDate+PINCacheTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDate+PINCacheTests.h"; sourceTree = "<group>"; };
C30EE1EA203717DE00D78CB9 /* NSDate+PINCacheTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDate+PINCacheTests.m"; sourceTree = "<group>"; };
CC0105B11E271A1600890935 /* PINCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINCache.framework; sourceTree = BUILT_PRODUCTS_DIR; };
CC0105C11E271A4000890935 /* PINCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINCache.framework; sourceTree = BUILT_PRODUCTS_DIR; };
CC0105CE1E271A4900890935 /* PINCache.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PINCache.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -313,6 +318,8 @@
children = (
CC0106CB1E28248A00890935 /* Assets */,
CC0106C51E281D6900890935 /* Info.plist */,
C30EE1E9203717DE00D78CB9 /* NSDate+PINCacheTests.h */,
C30EE1EA203717DE00D78CB9 /* NSDate+PINCacheTests.m */,
CC0106C91E28228300890935 /* PINCacheTests.h */,
CC01060D1E271A9000890935 /* PINCacheTests.m */,
);
Expand Down Expand Up @@ -672,6 +679,7 @@
buildActionMask = 2147483647;
files = (
CC0106C61E28226900890935 /* PINCacheTests.m in Sources */,
C30EE1F520373D1900D78CB9 /* NSDate+PINCacheTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -680,6 +688,7 @@
buildActionMask = 2147483647;
files = (
CC0106C71E28226A00890935 /* PINCacheTests.m in Sources */,
C30EE1F620373D1A00D78CB9 /* NSDate+PINCacheTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -688,6 +697,7 @@
buildActionMask = 2147483647;
files = (
CC0106C81E28226A00890935 /* PINCacheTests.m in Sources */,
C30EE1F720373D1B00D78CB9 /* NSDate+PINCacheTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
26 changes: 26 additions & 0 deletions Source/PINCache.m
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,26 @@ - (void)trimToDateAsync:(NSDate *)date completion:(PINCacheBlock)block
[group start];
}

- (void)removeExpiredObjectsAsync:(PINCacheBlock)block
{
PINOperationGroup *group = [PINOperationGroup asyncOperationGroupWithQueue:_operationQueue];

[group addOperation:^{
[_memoryCache removeExpiredObjects];
}];
[group addOperation:^{
[_diskCache removeExpiredObjects];
}];

if (block) {
[group setCompletion:^{
block(self);
}];
}

[group start];
}

#pragma mark - Public Synchronous Accessors -

- (NSUInteger)diskByteCount
Expand Down Expand Up @@ -330,6 +350,12 @@ - (void)trimToDate:(NSDate *)date
[_diskCache trimToDate:date];
}

- (void)removeExpiredObjects
{
[_memoryCache removeExpiredObjects];
[_diskCache removeExpiredObjects];
}

- (void)removeAllObjects
{
[_memoryCache removeAllObjects];
Expand Down
28 changes: 24 additions & 4 deletions Source/PINCaching.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ typedef void (^PINCacheObjectContainmentBlock)(BOOL containsObject);

@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
@param ageLimit The age limit (in seconds) to associate with the object.
@param ageLimit The age limit (in seconds) to associate with the object. An age limit <= 0 means there is no object-level age limit and the
cache-level TTL will be used for this object.
@param block A block to be executed concurrently after the object has been stored, or nil.
*/
- (void)setObjectAsync:(id)object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit completion:(nullable PINCacheObjectBlock)block;
Expand All @@ -112,7 +113,8 @@ typedef void (^PINCacheObjectContainmentBlock)(BOOL containsObject);
@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
@param cost An amount to add to the <memoryCache.totalCost>.
@param ageLimit The age limit (in seconds) to associate with the object.
@param ageLimit The age limit (in seconds) to associate with the object. An age limit <= 0 means there is no object-level age limit and the cache-level TTL will be
used for this object.
@param block A block to be executed concurrently after the object has been stored, or nil.
*/
- (void)setObjectAsync:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost ageLimit:(NSTimeInterval)ageLimit completion:(nullable PINCacheObjectBlock)block;
Expand All @@ -135,6 +137,15 @@ typedef void (^PINCacheObjectContainmentBlock)(BOOL containsObject);
*/
- (void)trimToDateAsync:(NSDate *)date completion:(nullable PINCacheBlock)block;

/**
Removes all expired objects from the cache. This includes objects that are considered expired due to the cache-level ageLimit
as well as object-level ageLimits. This method returns immediately and executes the passed block after the objects have been removed,
potentially in parallel with other blocks on the <concurrentQueue>.

@param block A block to be executed concurrently after the objects have been removed, or nil.
*/
- (void)removeExpiredObjectsAsync:(nullable PINCacheBlock)block;

/**
Removes all objects from the cache.This method returns immediately and executes the passed block after the
cache has been cleared, potentially in parallel with other blocks on the <concurrentQueue>.
Expand Down Expand Up @@ -183,7 +194,8 @@ typedef void (^PINCacheObjectContainmentBlock)(BOOL containsObject);
@see setObjectAsync:forKey:completion:
@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
@param ageLimit The age limit (in seconds) to associate with the object.
@param ageLimit The age limit (in seconds) to associate with the object. An age limit <= 0 means there is no
object-level age limit and the cache-level TTL will be used for this object.
*/
- (void)setObject:(nullable id)object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit;

Expand All @@ -206,7 +218,8 @@ typedef void (^PINCacheObjectContainmentBlock)(BOOL containsObject);
@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
@param cost An amount to add to the <memoryCache.totalCost>.
@param ageLimit The age limit (in seconds) to associate with the object.
@param ageLimit The age limit (in seconds) to associate with the object. An age limit <= 0 means there is no object-level age
limit and the cache-level TTL will be used for this object.
*/
- (void)setObject:(nullable id)object forKey:(NSString *)key withCost:(NSUInteger)cost ageLimit:(NSTimeInterval)ageLimit;

Expand All @@ -230,6 +243,13 @@ typedef void (^PINCacheObjectContainmentBlock)(BOOL containsObject);
*/
- (void)trimToDate:(NSDate *)date;

/**
Removes all expired objects from the cache. This includes objects that are considered expired due to the cache-level ageLimit
as well as object-level ageLimits. This method blocks the calling thread until the objects have been removed.
Uses a lock to achieve synchronicity on the disk cache.
*/
- (void)removeExpiredObjects;

/**
Removes all objects from the cache. This method blocks the calling thread until the cache has been cleared.
Uses a lock to achieve synchronicity on the disk cache.
Expand Down
21 changes: 17 additions & 4 deletions Source/PINDiskCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ NS_ASSUME_NONNULL_BEGIN
@class PINOperationQueue;

extern NSString * const PINDiskCacheErrorDomain;
extern NSErrorUserInfoKey const PINDiskCacheErrorReadFailureCodeKey;
extern NSErrorUserInfoKey const PINDiskCacheErrorWriteFailureCodeKey;
extern NSString * const PINDiskCachePrefix;

typedef NS_ENUM(NSInteger, PINDiskCacheError) {
PINDiskCacheErrorWriteFailure = -1000,
PINDiskCacheErrorReadFailure = -1000,
PINDiskCacheErrorWriteFailure = -1001,
};

/**
Expand Down Expand Up @@ -186,6 +188,10 @@ PIN_SUBCLASSING_RESTRICTED
- Accessing an object in the cache does not extend that object's lifetime in the cache
- When attempting to access an object in the cache that has lived longer than self.ageLimit,
the cache will behave as if the object does not exist

@note If an object-level age limit is set via one of the @c -setObject:forKey:withAgeLimit methods,
that age limit overrides self.ageLimit. The overridden object age limit could be greater or less
than self.agelimit but must be greater than zero.

*/
@property (nonatomic, assign, getter=isTTLCache) BOOL ttlCache;
Expand Down Expand Up @@ -362,7 +368,8 @@ PIN_SUBCLASSING_RESTRICTED

@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
@param ageLimit The age limit (in seconds) to associate with the object.
@param ageLimit The age limit (in seconds) to associate with the object. An age limit <= 0 means there is no object-level age limit and the cache-level TTL
will be used for this object.
@param block A block to be executed serially after the object has been stored, or nil.
*/
- (void)setObjectAsync:(id <NSCoding>)object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit completion:(nullable PINDiskCacheObjectBlock)block;
Expand All @@ -389,7 +396,8 @@ PIN_SUBCLASSING_RESTRICTED
@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
@param cost An amount to add to the <memoryCache.totalCost>.
@param ageLimit The age limit (in seconds) to associate with the object.
@param ageLimit The age limit (in seconds) to associate with the object. An age limit <= 0 means there is no object-level age limit and the cache-level TTL will be used for
this object.
@param block A block to be executed concurrently after the object has been stored, or nil.
*/
- (void)setObjectAsync:(id <NSCoding>)object forKey:(NSString *)key withCost:(NSUInteger)cost ageLimit:(NSTimeInterval)ageLimit completion:(nullable PINCacheObjectBlock)block;
Expand Down Expand Up @@ -419,6 +427,8 @@ PIN_SUBCLASSING_RESTRICTED

@param byteCount The cache will be trimmed equal to or smaller than this size.
@param block A block to be executed serially after the cache has been trimmed, or nil.

@note This will not remove objects that have been added via one of the @c -setObject:forKey:withAgeLimit methods.
*/
- (void)trimToSizeByDateAsync:(NSUInteger)byteCount completion:(nullable PINCacheBlock)block;

Expand Down Expand Up @@ -489,7 +499,8 @@ PIN_SUBCLASSING_RESTRICTED
@see setObjectAsync:forKey:completion:
@param object An object to store in the cache.
@param key A key to associate with the object. This string will be copied.
@param ageLimit The age limit (in seconds) to associate with the object.
@param ageLimit The age limit (in seconds) to associate with the object. An age limit <= 0 means there is
no object-level age limit and the cache-level TTL will be used for this object.
*/
- (void)setObject:(nullable id <NSCoding>)object forKey:(NSString *)key withAgeLimit:(NSTimeInterval)ageLimit;

Expand All @@ -508,6 +519,8 @@ PIN_SUBCLASSING_RESTRICTED

@see trimToSizeByDateAsync:
@param byteCount The cache will be trimmed equal to or smaller than this size.

@note This will not remove objects that have been added via one of the @c -setObject:forKey:withAgeLimit methods.
*/
- (void)trimToSizeByDate:(NSUInteger)byteCount;

Expand Down
Loading