Skip to content

Commit

Permalink
feat: Using config to decide base query or delta query (#386)
Browse files Browse the repository at this point in the history
  • Loading branch information
wooj2 authored Apr 22, 2020
1 parent 3986cf5 commit b02c3b7
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,24 @@ final class InitialSyncOperation: AsynchronousOperation {
}

let lastSyncMetadata = getLastSyncMetadata()
lastSyncTime = lastSyncMetadata?.lastSync
guard let lastSync = lastSyncMetadata?.lastSync else {
return
}

//TODO: Update to use TimeInterval.milliseconds when it is pushed to master branch
// https://github.com/aws-amplify/amplify-ios/issues/398
let lastSyncDate = Date(timeIntervalSince1970: TimeInterval(lastSync) / 1_000)
let secondsSinceLastSync = (lastSyncDate.timeIntervalSinceNow * -1)
if secondsSinceLastSync < 0 {
log.info("lastSyncTime was in the future, assuming base query")
lastSyncTime = nil
return
}

let shouldDoDeltaQuery = secondsSinceLastSync < dataStoreConfiguration.syncInterval
if shouldDoDeltaQuery {
lastSyncTime = lastSync
}
}

private func getLastSyncMetadata() -> ModelSyncMetadata? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ class InitialSyncOperationTests: XCTestCase {
/// - It reads sync metadata from storage
func testReadsMetadata() {
let responder = QueryRequestListenerResponder<PaginatedList<AnyModel>> { _, listener in
let startedAt = Int(Date().timeIntervalSince1970)
let list = PaginatedList<AnyModel>(items: [], nextToken: nil, startedAt: startedAt)
let startDateMilliseconds = Int(Date().timeIntervalSince1970) * 1_000
let list = PaginatedList<AnyModel>(items: [], nextToken: nil, startedAt: startDateMilliseconds)
let event: GraphQLOperation<PaginatedList<AnyModel>>.Event = .completed(.success(list))
listener?(event)
return nil
Expand Down Expand Up @@ -63,8 +63,8 @@ class InitialSyncOperationTests: XCTestCase {
func testQueriesAPI() {
let apiWasQueried = expectation(description: "API was queried for a PaginatedList of AnyModel")
let responder = QueryRequestListenerResponder<PaginatedList<AnyModel>> { _, listener in
let startedAt = Int(Date().timeIntervalSince1970)
let list = PaginatedList<AnyModel>(items: [], nextToken: nil, startedAt: startedAt)
let startDateMilliseconds = Int(Date().timeIntervalSince1970) * 1_000
let list = PaginatedList<AnyModel>(items: [], nextToken: nil, startedAt: startDateMilliseconds)
let event: GraphQLOperation<PaginatedList<AnyModel>>.Event = .completed(.success(list))
listener?(event)
apiWasQueried.fulfill()
Expand Down Expand Up @@ -97,8 +97,8 @@ class InitialSyncOperationTests: XCTestCase {
/// - The method invokes a completion callback when complete
func testInvokesCompletionCallback() {
let responder = QueryRequestListenerResponder<PaginatedList<AnyModel>> { _, listener in
let startedAt = Int(Date().timeIntervalSince1970)
let list = PaginatedList<AnyModel>(items: [], nextToken: nil, startedAt: startedAt)
let startDateMilliseconds = Int(Date().timeIntervalSince1970) * 1_000
let list = PaginatedList<AnyModel>(items: [], nextToken: nil, startedAt: startDateMilliseconds)
let event: GraphQLOperation<PaginatedList<AnyModel>>.Event = .completed(.success(list))
listener?(event)
return nil
Expand Down Expand Up @@ -173,15 +173,15 @@ class InitialSyncOperationTests: XCTestCase {
/// - The method submits the returned data to the reconciliation queue
func testSubmitsToReconciliationQueue() {
let responder = QueryRequestListenerResponder<PaginatedList<AnyModel>> { _, listener in
let startedAt = Int(Date().timeIntervalSince1970)
let startedAtMilliseconds = Int(Date().timeIntervalSince1970) * 1_000
let model = MockSynced(id: "1")
let anyModel = AnyModel(model)
let metadata = MutationSyncMetadata(id: "1",
deleted: false,
lastChangedAt: Int(Date().timeIntervalSince1970),
version: 1)
let mutationSync = MutationSync(model: anyModel, syncMetadata: metadata)
let list = PaginatedList<AnyModel>(items: [mutationSync], nextToken: nil, startedAt: startedAt)
let list = PaginatedList<AnyModel>(items: [mutationSync], nextToken: nil, startedAt: startedAtMilliseconds)
let event: GraphQLOperation<PaginatedList<AnyModel>>.Event = .completed(.success(list))
listener?(event)
return nil
Expand Down Expand Up @@ -221,9 +221,9 @@ class InitialSyncOperationTests: XCTestCase {
/// - Then:
/// - The method submits the returned data to the reconciliation queue
func testUpdatesSyncMetadata() throws {
let startDateSeconds = Int(Date().timeIntervalSince1970)
let startDateMilliseconds = Int(Date().timeIntervalSince1970) * 1_000
let responder = QueryRequestListenerResponder<PaginatedList<AnyModel>> { _, listener in
let startedAt = startDateSeconds
let startedAt = startDateMilliseconds
let list = PaginatedList<AnyModel>(items: [], nextToken: nil, startedAt: startedAt)
let event: GraphQLOperation<PaginatedList<AnyModel>>.Event = .completed(.success(list))
listener?(event)
Expand Down Expand Up @@ -256,7 +256,7 @@ class InitialSyncOperationTests: XCTestCase {
return
}

XCTAssertEqual(syncMetadata.lastSync, startDateSeconds)
XCTAssertEqual(syncMetadata.lastSync, startDateMilliseconds)
}

/// - Given: An InitialSyncOperation in a system with previous sync metadata
Expand All @@ -266,12 +266,12 @@ class InitialSyncOperationTests: XCTestCase {
/// - It performs a sync query against the API category with a "lastSync" time from the last start time of
/// the stored metadata
func testQueriesFromLastSync() throws {
let startDateSeconds = Int(Date().timeIntervalSince1970) - 100
let startDateMilliseconds = (Int(Date().timeIntervalSince1970) - 100) * 1_000

let storageAdapter = try SQLiteStorageEngineAdapter(connection: Connection(.inMemory))
try storageAdapter.setUp(models: StorageEngine.systemModels + [MockSynced.self])

let syncMetadata = ModelSyncMetadata(id: MockSynced.modelName, lastSync: startDateSeconds)
let syncMetadata = ModelSyncMetadata(id: MockSynced.modelName, lastSync: startDateMilliseconds)
let syncMetadataSaved = expectation(description: "Sync metadata saved")
storageAdapter.save(syncMetadata) { result in
switch result {
Expand All @@ -286,7 +286,7 @@ class InitialSyncOperationTests: XCTestCase {
let apiWasQueried = expectation(description: "API was queried for a PaginatedList of AnyModel")
let responder = QueryRequestListenerResponder<PaginatedList<AnyModel>> { request, listener in
let lastSync = request.variables?["lastSync"] as? Int
XCTAssertEqual(lastSync, startDateSeconds)
XCTAssertEqual(lastSync, startDateMilliseconds)

let list = PaginatedList<AnyModel>(items: [], nextToken: nil, startedAt: nil)
let event: GraphQLOperation<PaginatedList<AnyModel>>.Event = .completed(.success(list))
Expand All @@ -310,4 +310,52 @@ class InitialSyncOperationTests: XCTestCase {

wait(for: [apiWasQueried], timeout: 1.0)
}

func testBaseQueryWhenExpiredLastSync() throws {
//Set start date to 100 seconds in the past
let startDateMilliSeconds = (Int(Date().timeIntervalSince1970) - 100) * 1_000

let storageAdapter = try SQLiteStorageEngineAdapter(connection: Connection(.inMemory))
try storageAdapter.setUp(models: StorageEngine.systemModels + [MockSynced.self])

let syncMetadata = ModelSyncMetadata(id: MockSynced.modelName, lastSync: startDateMilliSeconds)
let syncMetadataSaved = expectation(description: "Sync metadata saved")
storageAdapter.save(syncMetadata) { result in
switch result {
case .failure(let dataStoreError):
XCTAssertNil(dataStoreError)
case .success:
syncMetadataSaved.fulfill()
}
}
wait(for: [syncMetadataSaved], timeout: 1.0)

let apiWasQueried = expectation(description: "API was queried for a PaginatedList of AnyModel")
let responder = QueryRequestListenerResponder<PaginatedList<AnyModel>> { request, listener in
let lastSync = request.variables?["lastSync"] as? Int
XCTAssertNil(lastSync)

let list = PaginatedList<AnyModel>(items: [], nextToken: nil, startedAt: nil)
let event: GraphQLOperation<PaginatedList<AnyModel>>.Event = .completed(.success(list))
listener?(event)
apiWasQueried.fulfill()
return nil
}

let apiPlugin = MockAPICategoryPlugin()
apiPlugin.responders[.queryRequestListener] = responder

let reconciliationQueue = MockReconciliationQueue()
let configuration = DataStoreConfiguration.custom(syncInterval: 60)
let operation = InitialSyncOperation(
modelType: MockSynced.self,
api: apiPlugin,
reconciliationQueue: reconciliationQueue,
storageAdapter: storageAdapter,
dataStoreConfiguration: configuration) {_ in }

operation.main()

wait(for: [apiWasQueried], timeout: 1.0)
}
}

0 comments on commit b02c3b7

Please sign in to comment.