push eventamplitude/Amplitude-iOS
commit sha a52d34fb142d3b927ef4ef50cd5766ecdef8b096
Add copyright header for Amplitude
push time in 18 hours
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
+//
Oh sorry, that's the wrong header. I didn't realize you were talking about a copyright
comment created time in 19 hours
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
+//
Why is is resolved? Amplitude copyright is needed for all new files.
comment created time in 20 hours
push eventamplitude/Amplitude-iOS
commit sha 3bffb3b26671dd16eccf804a1f773d0d8f29c9e6
Fix error case of unclosed JSON (no ending bracket), try finishing the file and do it again
push time in 21 hours
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
+//+// File.m+//+//+// Created by Dante Tam on 6/10/21.+//++#import <Foundation/Foundation.h>+#import <Amplitude.h>+#import "AMPStorage.h"++@implementation AMPStorage+++ (NSString *)getAppStorageAmpDir:(NSString *)instanceName {+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);+ NSString *path = [paths firstObject];+ NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];+ return [NSString stringWithFormat:@"%@/%@/%@", path, bundleIdentifier, instanceName];
I just tested it when I made the PR. It goes to $default_instance
comment created time in a day
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
+//+// File.m+//+//+// Created by Dante Tam on 6/10/21.+//++#import <Foundation/Foundation.h>+#import <Amplitude.h>+#import "AMPStorage.h"++@implementation AMPStorage+++ (NSString *)getAppStorageAmpDir:(NSString *)instanceName {+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);+ NSString *path = [paths firstObject];+ NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];+ return [NSString stringWithFormat:@"%@/%@/%@", path, bundleIdentifier, instanceName];
What if instanceName is nil?
comment created time in a day
push eventamplitude/Amplitude-iOS
commit sha 0e2d08b778fe3766e07cdf69c32d37e5d43bcdab
reset some memory variables, add instance name as parameter to saved event files
push time in a day
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
+//+// File.m+//+//+// Created by Dante Tam on 6/10/21.+//++#import <Foundation/Foundation.h>+#import <Amplitude.h>+#import "AMPStorage.h"++@implementation AMPStorage+++ (NSString *)getAppStorageAmpDir {+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);+ NSString *path = [paths firstObject];+ NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];+ return [NSString stringWithFormat:@"%@/%@/%@", path, @"/", bundleIdentifier];+}+++ (NSString *)getDefaultEventsFile {+ NSString *baseDir = [AMPStorage getAppStorageAmpDir];+ NSString *path = [baseDir stringByAppendingString:@"/amplitude_event_storage.txt"];
Oh yeah, if we have multiple instances, we should use different files. Instance name should be passed as a parameter now
comment created time in a day
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
+//+// File.m+//+//+// Created by Dante Tam on 6/10/21.+//++#import <Foundation/Foundation.h>+#import <Amplitude.h>+#import "AMPStorage.h"++@implementation AMPStorage+++ (NSString *)getAppStorageAmpDir {+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);+ NSString *path = [paths firstObject];+ NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];+ return [NSString stringWithFormat:@"%@/%@/%@", path, @"/", bundleIdentifier];+}+++ (NSString *)getDefaultEventsFile {+ NSString *baseDir = [AMPStorage getAppStorageAmpDir];+ NSString *path = [baseDir stringByAppendingString:@"/amplitude_event_storage.txt"];
Another question here. Originally, we have different databases for different instance names. Should we also consider naming .txt file-related instance name here?
comment created time in a day
issue commentamplitude/Amplitude-JavaScript
Is there any possibility the device id to be duplicated?
Hey @jason-hwang,
-
We use v4 UUID generation for device_ids so the theoretical entropy of this is 1 collision in ~10^18 device ID's, in practice limited by the entropy of JS's
Math.random(). My gut feeling is that 400 collisions is still a little high for 100,000 ID's so happy to work with you to debug this. How did you come about finding this issue? -
You can use that to regenerate the device ID, yes.
comment created time in a day
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
- (void)makeEventUploadPostRequest:(NSString *)url events:(NSString *)events num // If blocked by one massive event, drop it if (numEvents == 1) { if (maxEventId >= 0) {- (void) [self.dbHelper removeEvent:maxEventId];+ self->_eventsBuffer = [[NSMutableArray alloc] init];
Also fixed this.
comment created time in a day
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
- (void)makeEventUploadPostRequest:(NSString *)url events:(NSString *)events num // success, remove existing events from dictionary uploadSuccessful = YES; if (maxEventId >= 0) {- (void) [self.dbHelper removeEvents:maxEventId];+ [AMPStorage remove:[AMPStorage getDefaultEventsFile]];
Good catch.
comment created time in a day
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
- (void)makeEventUploadPostRequest:(NSString *)url events:(NSString *)events num // success, remove existing events from dictionary uploadSuccessful = YES; if (maxEventId >= 0) {- (void) [self.dbHelper removeEvents:maxEventId];+ [AMPStorage remove:[AMPStorage getDefaultEventsFile]];
Do we need to handle the _eventsBuffer in this case?
comment created time in a day
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
- (void)makeEventUploadPostRequest:(NSString *)url events:(NSString *)events num // If blocked by one massive event, drop it if (numEvents == 1) { if (maxEventId >= 0) {- (void) [self.dbHelper removeEvent:maxEventId];+ self->_eventsBuffer = [[NSMutableArray alloc] init];
If it falls into this case, do we need to anything about the file? I guess the massive event in this case is already saved on the file?
comment created time in a day
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
- (void)enterBackground { self->_inForeground = NO; [self refreshSessionTime:now]; [self uploadEventsWithLimit:0];+ [AMPStorage finish:[AMPStorage getDefaultEventsFile]];
That's a good catch. One simple way of handling that is to run finish if we see a JSON parsing error anywhere, and then try again
comment created time in a day
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
- (void)uploadEventsWithLimit:(int)limit { return; } - long eventCount = [self.dbHelper getTotalEventCount];+ long eventCount = [self->_eventsBuffer count]; long numEvents = limit > 0 ? fminl(eventCount, limit) : eventCount; if (numEvents == 0) { self->_updatingCurrently = NO; [self endBackgroundTaskIfNeeded]; return; }- NSMutableArray *events = [self.dbHelper getEvents:-1 limit:numEvents];- NSMutableArray *identifys = [self.dbHelper getIdentifys:-1 limit:numEvents];- NSDictionary *merged = [self mergeEventsAndIdentifys:events identifys:identifys numEvents:numEvents];+ + long identifyCount = [self->_identifyBuffer count];+ long numIdentify = limit > 0 ? fminl(identifyCount, limit) : identifyCount;+ + NSMutableArray *events = [[self->_eventsBuffer subarrayWithRange:NSMakeRange(0, numEvents)] mutableCopy];+ NSMutableArray *identifys = [[self->_identifyBuffer subarrayWithRange:NSMakeRange(0, numIdentify)] mutableCopy];+ NSDictionary *merged = [self mergeEventsAndIdentifys:events identifys:identifys numEvents:(numEvents+numIdentify)]; + for (NSDictionary *event in events) {+ // convert event dictionary to JSON String+ NSError *error = nil;+ NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[AMPUtils makeJSONSerializable:event] options:0 error:&error];+ if (error != nil) {+ AMPLITUDE_ERROR(@"ERROR: could not JSONSerialize event type: %@", error);+ continue;+ }+ NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];+ if ([AMPUtils isEmptyString:jsonString]) {+ AMPLITUDE_ERROR(@"ERROR: JSONSerializing event type event resulted in an NULL string");+ continue;+ }+ [AMPStorage storeEvent:jsonString];
Yes, there's better improvements for doing it as a batch. It's better to write to disk at once than many times elsewhere. Maybe this approach could go back to streaming if we used NSOutputStream. I got really good results using a batch, see the slack chat where I zipped some time profiles.
comment created time in a day
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
- (void)uploadEventsWithLimit:(int)limit { return; } - long eventCount = [self.dbHelper getTotalEventCount];+ long eventCount = [self->_eventsBuffer count]; long numEvents = limit > 0 ? fminl(eventCount, limit) : eventCount; if (numEvents == 0) { self->_updatingCurrently = NO; [self endBackgroundTaskIfNeeded]; return; }- NSMutableArray *events = [self.dbHelper getEvents:-1 limit:numEvents];- NSMutableArray *identifys = [self.dbHelper getIdentifys:-1 limit:numEvents];- NSDictionary *merged = [self mergeEventsAndIdentifys:events identifys:identifys numEvents:numEvents];+ + long identifyCount = [self->_identifyBuffer count];+ long numIdentify = limit > 0 ? fminl(identifyCount, limit) : identifyCount;+ + NSMutableArray *events = [[self->_eventsBuffer subarrayWithRange:NSMakeRange(0, numEvents)] mutableCopy];+ NSMutableArray *identifys = [[self->_identifyBuffer subarrayWithRange:NSMakeRange(0, numIdentify)] mutableCopy];+ NSDictionary *merged = [self mergeEventsAndIdentifys:events identifys:identifys numEvents:(numEvents+numIdentify)]; + for (NSDictionary *event in events) {+ // convert event dictionary to JSON String+ NSError *error = nil;+ NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[AMPUtils makeJSONSerializable:event] options:0 error:&error];+ if (error != nil) {+ AMPLITUDE_ERROR(@"ERROR: could not JSONSerialize event type: %@", error);+ continue;+ }+ NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];+ if ([AMPUtils isEmptyString:jsonString]) {+ AMPLITUDE_ERROR(@"ERROR: JSONSerializing event type event resulted in an NULL string");+ continue;+ }+ [AMPStorage storeEvent:jsonString];
So we are changing from storeEvent on event creation, and we save the events to file before upload happens. Is there any difference or performance improvements we can see by this way? And with this change, we just rely on memory more and can still lose events before we call upload?
comment created time in a day
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
- (void)enterBackground { self->_inForeground = NO; [self refreshSessionTime:now]; [self uploadEventsWithLimit:0];+ [AMPStorage finish:[AMPStorage getDefaultEventsFile]];
What would happen if this not get triggered? Like killed by memory management? That time this may not be triggered.
comment created time in a day
push eventamplitude/Amplitude-iOS
commit sha 113d4b9a700f5e77d78166692e4063bbafc04303
Remove from old dbhelper operations, fix PR more to align with my ticket
push time in a day
issue openedamplitude/Amplitude-JavaScript
Is there any possibility the device id to be duplicated?
Summary
The duplicated device id is observed in my service. (almost 100,000 device ids is collected)
Question 1
Is there any possibility the device id to be duplicated?
Question 2
If Q1 yes, to avoid the situation, does I have to use the re-generate method of amplitude's instance?
-> amplitude.getInstance().regenerateDeviceId()
created time in 2 days
push eventamplitude/Amplitude-iOS
commit sha ce55f3e702920509302cd03edb95c13fead673ef
Fix up PR
push time in 2 days
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
+//+// File.m+//+//+// Created by Dante Tam on 6/10/21.+//++#import <Foundation/Foundation.h>++#import "AMPStorage.h"++@interface AMPStorage ()+@end++@implementation AMPStorage {+ +}+++ (NSString *)getAppStorageAmpDir {+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);+ NSString *path = [paths firstObject];+ NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];+ return [NSString stringWithFormat:@"%@/%@/%@", path, @"/", bundleIdentifier];+}+++ (NSString *)getDefaultEventsFile {+ NSString *baseDir = [AMPStorage getAppStorageAmpDir];+ NSString *path = [baseDir stringByAppendingString:@"/amplitude_event_storage.txt"];+ return path;+}+++ (NSString *)getDefaultIdentifyFile {+ NSString *baseDir = [AMPStorage getAppStorageAmpDir];+ NSString *path = [baseDir stringByAppendingString:@"/amplitude_identify_storage.txt"];+ return path;+}+++ (void)storeEvent:(NSString *) event {+ NSString *path = [AMPStorage getDefaultEventsFile];+ NSURL *url = [NSURL fileURLWithPath:path];+ [AMPStorage storeEventAtUrl:url event:event];+}+++ (void)storeIdentify:(NSString *) event {+ NSString *path = [AMPStorage getDefaultIdentifyFile];+ NSURL *url = [NSURL fileURLWithPath:path];+ [AMPStorage storeEventAtUrl:url event:event];+}+++ (void)storeEventAtUrl:(NSURL *)url event:(NSString *)event {+ NSFileManager *fm = [NSFileManager defaultManager];+ NSString *path = [AMPStorage getDefaultEventsFile];+ + bool newFile = false;+ if (![fm fileExistsAtPath:path]) {+ [AMPStorage start:path];+ newFile = true;+ }+ + NSData *jsonData = [event dataUsingEncoding:NSUTF8StringEncoding];+ NSFileHandle *handle = [NSFileHandle fileHandleForWritingToURL:url error:nil];+ [handle seekToEndOfFile];+ if (!newFile) {+ [handle writeData:[@"," dataUsingEncoding:NSUTF8StringEncoding]];+ }+ [handle writeData:jsonData];+ //[handle closeFile];+}+++ (void)start:(NSString *)path {+ NSString *contents = @"{ \"batch\": [";
This is fine. Resolved.
comment created time in 2 days
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
- (void)enterBackground { self->_inForeground = NO; [self refreshSessionTime:now]; [self uploadEventsWithLimit:0];+ [AMPStorage finish:[AMPStorage getDefaultEventsFile]];
This finish method only does work if the appropriate file exists.
comment created time in 2 days
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
+//+// File.m+//+//+// Created by Dante Tam on 6/10/21.+//++#import <Foundation/Foundation.h>++#import "AMPStorage.h"++@interface AMPStorage ()+@end++@implementation AMPStorage {+ +}+++ (NSString *)getAppStorageAmpDir {+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);+ NSString *path = [paths firstObject];+ NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];+ return [NSString stringWithFormat:@"%@/%@/%@", path, @"/", bundleIdentifier];+}+++ (NSString *)getDefaultEventsFile {+ NSString *baseDir = [AMPStorage getAppStorageAmpDir];+ NSString *path = [baseDir stringByAppendingString:@"/amplitude_event_storage.txt"];+ return path;+}+++ (NSString *)getDefaultIdentifyFile {+ NSString *baseDir = [AMPStorage getAppStorageAmpDir];+ NSString *path = [baseDir stringByAppendingString:@"/amplitude_identify_storage.txt"];+ return path;+}+++ (void)storeEvent:(NSString *) event {+ NSString *path = [AMPStorage getDefaultEventsFile];+ NSURL *url = [NSURL fileURLWithPath:path];+ [AMPStorage storeEventAtUrl:url event:event];+}+++ (void)storeIdentify:(NSString *) event {+ NSString *path = [AMPStorage getDefaultIdentifyFile];+ NSURL *url = [NSURL fileURLWithPath:path];+ [AMPStorage storeEventAtUrl:url event:event];+}+++ (void)storeEventAtUrl:(NSURL *)url event:(NSString *)event {+ NSFileManager *fm = [NSFileManager defaultManager];+ NSString *path = [AMPStorage getDefaultEventsFile];+ + bool newFile = false;+ if (![fm fileExistsAtPath:path]) {+ [AMPStorage start:path];+ newFile = true;+ }+ + NSData *jsonData = [event dataUsingEncoding:NSUTF8StringEncoding];+ NSFileHandle *handle = [NSFileHandle fileHandleForWritingToURL:url error:nil];+ [handle seekToEndOfFile];+ if (!newFile) {+ [handle writeData:[@"," dataUsingEncoding:NSUTF8StringEncoding]];+ }+ [handle writeData:jsonData];+ //[handle closeFile];+}+++ (void)start:(NSString *)path {+ NSString *contents = @"{ \"batch\": [";
It's for keeping the JSON object structured so that it's not just an array. There may be other data associated with this file. The original use in Segment API is that they also added the upload date as a second key-value property in this file.
comment created time in 2 days
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
- (void)enterBackground { self->_inForeground = NO; [self refreshSessionTime:now]; [self uploadEventsWithLimit:0];+ [AMPStorage finish:[AMPStorage getDefaultEventsFile]];
If I have no events at all, will this crash my app?
comment created time in 2 days
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
+//+// File.m+//+//+// Created by Dante Tam on 6/10/21.+//++#import <Foundation/Foundation.h>++#import "AMPStorage.h"++@interface AMPStorage ()+@end++@implementation AMPStorage {
That's the old way for declaring properties inside curly bracket.
comment created time in 2 days
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
typedef NSDictionary *_Nullable (^AMPLocationInfoBlock)(void); */ - (void)logEvent:(NSString *)eventType; +- (void)theTest;
Don't forget to remove this.
comment created time in 2 days
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
+//+// File.m+//+//+// Created by Dante Tam on 6/10/21.+//++#import <Foundation/Foundation.h>++#import "AMPStorage.h"++@interface AMPStorage ()+@end++@implementation AMPStorage {+ +}+++ (NSString *)getAppStorageAmpDir {+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);+ NSString *path = [paths firstObject];+ NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];+ return [NSString stringWithFormat:@"%@/%@/%@", path, @"/", bundleIdentifier];+}+++ (NSString *)getDefaultEventsFile {+ NSString *baseDir = [AMPStorage getAppStorageAmpDir];+ NSString *path = [baseDir stringByAppendingString:@"/amplitude_event_storage.txt"];+ return path;+}+++ (NSString *)getDefaultIdentifyFile {+ NSString *baseDir = [AMPStorage getAppStorageAmpDir];+ NSString *path = [baseDir stringByAppendingString:@"/amplitude_identify_storage.txt"];+ return path;+}+++ (void)storeEvent:(NSString *) event {+ NSString *path = [AMPStorage getDefaultEventsFile];+ NSURL *url = [NSURL fileURLWithPath:path];+ [AMPStorage storeEventAtUrl:url event:event];+}+++ (void)storeIdentify:(NSString *) event {+ NSString *path = [AMPStorage getDefaultIdentifyFile];+ NSURL *url = [NSURL fileURLWithPath:path];+ [AMPStorage storeEventAtUrl:url event:event];+}+++ (void)storeEventAtUrl:(NSURL *)url event:(NSString *)event {+ NSFileManager *fm = [NSFileManager defaultManager];+ NSString *path = [AMPStorage getDefaultEventsFile];+ + bool newFile = false;+ if (![fm fileExistsAtPath:path]) {+ [AMPStorage start:path];+ newFile = true;+ }+ + NSData *jsonData = [event dataUsingEncoding:NSUTF8StringEncoding];+ NSFileHandle *handle = [NSFileHandle fileHandleForWritingToURL:url error:nil];+ [handle seekToEndOfFile];+ if (!newFile) {+ [handle writeData:[@"," dataUsingEncoding:NSUTF8StringEncoding]];+ }+ [handle writeData:jsonData];+ //[handle closeFile];
remove or keep?
comment created time in 2 days
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
+//+// File.m+//+//+// Created by Dante Tam on 6/10/21.+//++#import <Foundation/Foundation.h>++#import "AMPStorage.h"++@interface AMPStorage ()+@end++@implementation AMPStorage {+ +}+++ (NSString *)getAppStorageAmpDir {+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);+ NSString *path = [paths firstObject];+ NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];+ return [NSString stringWithFormat:@"%@/%@/%@", path, @"/", bundleIdentifier];+}+++ (NSString *)getDefaultEventsFile {+ NSString *baseDir = [AMPStorage getAppStorageAmpDir];+ NSString *path = [baseDir stringByAppendingString:@"/amplitude_event_storage.txt"];+ return path;+}+++ (NSString *)getDefaultIdentifyFile {+ NSString *baseDir = [AMPStorage getAppStorageAmpDir];+ NSString *path = [baseDir stringByAppendingString:@"/amplitude_identify_storage.txt"];+ return path;+}+++ (void)storeEvent:(NSString *) event {+ NSString *path = [AMPStorage getDefaultEventsFile];+ NSURL *url = [NSURL fileURLWithPath:path];+ [AMPStorage storeEventAtUrl:url event:event];+}+++ (void)storeIdentify:(NSString *) event {+ NSString *path = [AMPStorage getDefaultIdentifyFile];+ NSURL *url = [NSURL fileURLWithPath:path];+ [AMPStorage storeEventAtUrl:url event:event];+}+++ (void)storeEventAtUrl:(NSURL *)url event:(NSString *)event {
If all the operations are queued into the same queue to execute, then it should be fine. We need to guarantee that.
comment created time in 2 days
Pull request review commentamplitude/Amplitude-iOS
perf: Localstorage I/O optimization and batching strategies, streaming to disk
- (void)enterBackground { self->_inForeground = NO; [self refreshSessionTime:now]; [self uploadEventsWithLimit:0];+ [AMPStorage finish:[AMPStorage getDefaultEventsFile]];
Need to verify if this will be triggered when killing the app.
comment created time in 2 days