private static void configurePushTransitions( ITransitionConfigurator transitions, ITogglApi api, ITogglDataSource dataSource, IAnalyticsService analyticsService, ILeakyBucket minutesLeakyBucket, IRateLimiter rateLimiter, IScheduler scheduler, StateResult entryPoint, DependencyContainer dependencyContainer) { var delayState = new WaitForAWhileState(scheduler, analyticsService); var pushNotificationsToken = new SyncPushNotificationsTokenState(dependencyContainer.PushNotificationsTokenStorage, api, dependencyContainer.PushNotificationsTokenService, dependencyContainer.TimeService, dependencyContainer.RemoteConfigService); transitions.ConfigureTransition(entryPoint, pushNotificationsToken); var pushingWorkspaces = configureCreateOnlyPush(transitions, pushNotificationsToken.Done, dataSource.Workspaces, analyticsService, api.Workspaces, minutesLeakyBucket, rateLimiter, delayState, Workspace.Clean, Workspace.Unsyncable); var pushingUsers = configurePushSingleton(transitions, pushingWorkspaces.NoMoreChanges, dataSource.User, analyticsService, api.User, minutesLeakyBucket, rateLimiter, delayState, User.Clean, User.Unsyncable); var pushingPreferences = configurePushSingleton(transitions, pushingUsers.NoMoreChanges, dataSource.Preferences, analyticsService, api.Preferences, minutesLeakyBucket, rateLimiter, delayState, Preferences.Clean, Preferences.Unsyncable); var pushingTags = configureCreateOnlyPush(transitions, pushingPreferences.NoMoreChanges, dataSource.Tags, analyticsService, api.Tags, minutesLeakyBucket, rateLimiter, delayState, Tag.Clean, Tag.Unsyncable); var pushingClients = configureCreateOnlyPush(transitions, pushingTags.NoMoreChanges, dataSource.Clients, analyticsService, api.Clients, minutesLeakyBucket, rateLimiter, delayState, Client.Clean, Client.Unsyncable); var pushingProjects = configureCreateOnlyPush(transitions, pushingClients.NoMoreChanges, dataSource.Projects, analyticsService, api.Projects, minutesLeakyBucket, rateLimiter, delayState, Project.Clean, Project.Unsyncable); var pushingTimeEntries = configurePush(transitions, pushingProjects.NoMoreChanges, dataSource.TimeEntries, analyticsService, api.TimeEntries, api.TimeEntries, api.TimeEntries, minutesLeakyBucket, rateLimiter, delayState, TimeEntry.Clean, TimeEntry.Unsyncable); transitions.ConfigureTransition(delayState.Done, pushingWorkspaces); transitions.ConfigureTransition(pushingTimeEntries.NoMoreChanges, new DeadEndState()); }
private static void configureCleanUpTransitions( ITransitionConfigurator transitions, ITimeService timeService, ITogglDataSource dataSource, StateResult entryPoint) { var deleteOlderEntries = new DeleteOldEntriesState(timeService, dataSource.TimeEntries); var deleteNonReferencedGhostProjects = new DeleteNonReferencedProjectGhostsState(dataSource.Projects, dataSource.TimeEntries); transitions.ConfigureTransition(entryPoint, deleteOlderEntries); transitions.ConfigureTransition(deleteOlderEntries.FinishedDeleting, deleteNonReferencedGhostProjects); }
private static void configurePullTransitions( ITransitionConfigurator transitions, ITogglDatabase database, ITogglApi api, ITogglDataSource dataSource, ITimeService timeService, IAnalyticsService analyticsService, IScheduler scheduler, StateResult entryPoint, IObservable <Unit> delayCancellation) { var rnd = new Random(); var apiDelay = new RetryDelayService(rnd); var statusDelay = new RetryDelayService(rnd); var fetchAllSince = new FetchAllSinceState(database, api, timeService); var persistWorkspaces = new PersistListState <IWorkspace, IDatabaseWorkspace, IThreadSafeWorkspace>(dataSource.Workspaces, Workspace.Clean); var updateWorkspacesSinceDate = new SinceDateUpdatingState <IWorkspace, IDatabaseWorkspace>(database.SinceParameters); var detectNoWorkspaceState = new NoWorkspaceDetectingState(); var persistWorkspaceFeatures = new PersistListState <IWorkspaceFeatureCollection, IDatabaseWorkspaceFeatureCollection, IThreadSafeWorkspaceFeatureCollection>( dataSource.WorkspaceFeatures, WorkspaceFeatureCollection.From); var persistUser = new PersistSingletonState <IUser, IDatabaseUser, IThreadSafeUser>(dataSource.User, User.Clean); var noDefaultWorkspaceTrackingState = new NoDefaultWorkspaceTrackingState(analyticsService); var persistTags = new PersistListState <ITag, IDatabaseTag, IThreadSafeTag>(dataSource.Tags, Tag.Clean); var updateTagsSinceDate = new SinceDateUpdatingState <ITag, IDatabaseTag>(database.SinceParameters); var persistClients = new PersistListState <IClient, IDatabaseClient, IThreadSafeClient>(dataSource.Clients, Client.Clean); var updateClientsSinceDate = new SinceDateUpdatingState <IClient, IDatabaseClient>(database.SinceParameters); var persistPreferences = new PersistSingletonState <IPreferences, IDatabasePreferences, IThreadSafePreferences>(dataSource.Preferences, Preferences.Clean); var persistProjects = new PersistListState <IProject, IDatabaseProject, IThreadSafeProject>(dataSource.Projects, Project.Clean); var updateProjectsSinceDate = new SinceDateUpdatingState <IProject, IDatabaseProject>(database.SinceParameters); var createGhostProjects = new CreateGhostProjectsState(dataSource.Projects, analyticsService); var persistTimeEntries = new PersistListState <ITimeEntry, IDatabaseTimeEntry, IThreadSafeTimeEntry>(dataSource.TimeEntries, TimeEntry.Clean); var updateTimeEntriesSinceDate = new SinceDateUpdatingState <ITimeEntry, IDatabaseTimeEntry>(database.SinceParameters); var persistTasks = new PersistListState <ITask, IDatabaseTask, IThreadSafeTask>(dataSource.Tasks, Task.Clean); var updateTasksSinceDate = new SinceDateUpdatingState <ITask, IDatabaseTask>(database.SinceParameters); var refetchInaccessibleProjects = new TryFetchInaccessibleProjectsState(dataSource.Projects, timeService, api.Projects); var retryOrThrow = new SevereApiExceptionsRethrowingState(); var checkServerStatus = new CheckServerStatusState(api, scheduler, apiDelay, statusDelay, delayCancellation); var finished = new ResetAPIDelayState(apiDelay); var deleteOlderEntries = new DeleteOldEntriesState(timeService, dataSource.TimeEntries); var deleteNonReferencedGhostProjects = new DeleteNonReferencedProjectGhostsState(dataSource.Projects, dataSource.TimeEntries); transitions.ConfigureTransition(entryPoint, fetchAllSince); transitions.ConfigureTransition(fetchAllSince.FetchStarted, persistWorkspaces); transitions.ConfigureTransition(persistWorkspaces.FinishedPersisting, updateWorkspacesSinceDate); transitions.ConfigureTransition(updateWorkspacesSinceDate.Finished, detectNoWorkspaceState); transitions.ConfigureTransition(detectNoWorkspaceState.Continue, persistUser); transitions.ConfigureTransition(persistUser.FinishedPersisting, noDefaultWorkspaceTrackingState); transitions.ConfigureTransition(noDefaultWorkspaceTrackingState.Continue, persistWorkspaceFeatures); transitions.ConfigureTransition(persistWorkspaceFeatures.FinishedPersisting, persistPreferences); transitions.ConfigureTransition(persistPreferences.FinishedPersisting, persistTags); transitions.ConfigureTransition(persistTags.FinishedPersisting, updateTagsSinceDate); transitions.ConfigureTransition(updateTagsSinceDate.Finished, persistClients); transitions.ConfigureTransition(persistClients.FinishedPersisting, updateClientsSinceDate); transitions.ConfigureTransition(updateClientsSinceDate.Finished, persistProjects); transitions.ConfigureTransition(persistProjects.FinishedPersisting, updateProjectsSinceDate); transitions.ConfigureTransition(updateProjectsSinceDate.Finished, persistTasks); transitions.ConfigureTransition(persistTasks.FinishedPersisting, updateTasksSinceDate); transitions.ConfigureTransition(updateTasksSinceDate.Finished, createGhostProjects); transitions.ConfigureTransition(createGhostProjects.FinishedPersisting, persistTimeEntries); transitions.ConfigureTransition(persistTimeEntries.FinishedPersisting, updateTimeEntriesSinceDate); transitions.ConfigureTransition(updateTimeEntriesSinceDate.Finished, refetchInaccessibleProjects); transitions.ConfigureTransition(refetchInaccessibleProjects.FetchNext, refetchInaccessibleProjects); transitions.ConfigureTransition(refetchInaccessibleProjects.FinishedPersisting, deleteOlderEntries); transitions.ConfigureTransition(deleteOlderEntries.FinishedDeleting, deleteNonReferencedGhostProjects); transitions.ConfigureTransition(persistWorkspaces.ErrorOccured, retryOrThrow); transitions.ConfigureTransition(persistUser.ErrorOccured, retryOrThrow); transitions.ConfigureTransition(persistWorkspaceFeatures.ErrorOccured, retryOrThrow); transitions.ConfigureTransition(persistPreferences.ErrorOccured, retryOrThrow); transitions.ConfigureTransition(persistTags.ErrorOccured, retryOrThrow); transitions.ConfigureTransition(persistClients.ErrorOccured, retryOrThrow); transitions.ConfigureTransition(persistProjects.ErrorOccured, retryOrThrow); transitions.ConfigureTransition(persistTasks.ErrorOccured, retryOrThrow); transitions.ConfigureTransition(createGhostProjects.ErrorOccured, retryOrThrow); transitions.ConfigureTransition(persistTimeEntries.ErrorOccured, retryOrThrow); transitions.ConfigureTransition(refetchInaccessibleProjects.ErrorOccured, retryOrThrow); transitions.ConfigureTransition(retryOrThrow.Retry, checkServerStatus); transitions.ConfigureTransition(checkServerStatus.Retry, checkServerStatus); transitions.ConfigureTransition(checkServerStatus.ServerIsAvailable, finished); transitions.ConfigureTransition(finished.Continue, fetchAllSince); }
private static IStateResult configurePushSingleton <TModel, TThreadsafe>( ITransitionConfigurator transitions, IStateResult entryPoint, ISingletonDataSource <TThreadsafe> dataSource, IAnalyticsService analyticsService, IUpdatingApiClient <TModel> updatingApi, Func <TModel, TThreadsafe> toClean, Func <TThreadsafe, string, TThreadsafe> toUnsyncable, ITogglApi api, IScheduler scheduler, IObservable <Unit> delayCancellation) where TModel : class where TThreadsafe : class, TModel, IThreadSafeModel, IDatabaseSyncable { var rnd = new Random(); var apiDelay = new RetryDelayService(rnd); var statusDelay = new RetryDelayService(rnd); var push = new PushSingleState <TThreadsafe>(dataSource); var pushOne = new PushOneEntityState <TThreadsafe>(); var update = new UpdateEntityState <TModel, TThreadsafe>(updatingApi, dataSource, analyticsService, toClean); var tryResolveClientError = new TryResolveClientErrorState <TThreadsafe>(); var unsyncable = new UnsyncableEntityState <TThreadsafe>(dataSource, toUnsyncable); var checkServerStatus = new CheckServerStatusState(api, scheduler, apiDelay, statusDelay, delayCancellation); var finished = new ResetAPIDelayState(apiDelay); transitions.ConfigureTransition(entryPoint, push); transitions.ConfigureTransition(push.PushEntity, pushOne); transitions.ConfigureTransition(pushOne.UpdateEntity, update); transitions.ConfigureTransition(pushOne.CreateEntity, new InvalidTransitionState($"Creating is not supported for {typeof(TModel).Name} during Push sync.")); transitions.ConfigureTransition(pushOne.DeleteEntity, new InvalidTransitionState($"Deleting is not supported for {typeof(TModel).Name} during Push sync.")); transitions.ConfigureTransition(pushOne.DeleteEntityLocally, new InvalidTransitionState($"Deleting locally is not supported for {typeof(TModel).Name} during Push sync.")); transitions.ConfigureTransition(update.ClientError, tryResolveClientError); transitions.ConfigureTransition(update.ServerError, checkServerStatus); transitions.ConfigureTransition(update.UnknownError, checkServerStatus); transitions.ConfigureTransition(tryResolveClientError.UnresolvedTooManyRequests, checkServerStatus); transitions.ConfigureTransition(tryResolveClientError.Unresolved, unsyncable); transitions.ConfigureTransition(checkServerStatus.Retry, checkServerStatus); transitions.ConfigureTransition(checkServerStatus.ServerIsAvailable, push); transitions.ConfigureTransition(update.UpdatingSucceeded, finished); transitions.ConfigureTransition(finished.Continue, push); return(push.NothingToPush); }
private static IStateResult configurePush <TModel, TDatabase, TThreadsafe>( ITransitionConfigurator transitions, IStateResult entryPoint, IDataSource <TThreadsafe, TDatabase> dataSource, IAnalyticsService analyticsService, ICreatingApiClient <TModel> creatingApi, IUpdatingApiClient <TModel> updatingApi, IDeletingApiClient <TModel> deletingApi, Func <TModel, TThreadsafe> toClean, Func <TThreadsafe, string, TThreadsafe> toUnsyncable, ITogglApi api, IRetryDelayService apiDelay, IScheduler scheduler, IObservable <Unit> delayCancellation) where TModel : class, IIdentifiable, ILastChangedDatable where TDatabase : class, TModel, IDatabaseSyncable where TThreadsafe : class, TDatabase, IThreadSafeModel { var rnd = new Random(); var statusDelay = new RetryDelayService(rnd); var push = new PushState <TDatabase, TThreadsafe>(dataSource); var pushOne = new PushOneEntityState <TThreadsafe>(); var create = new CreateEntityState <TModel, TThreadsafe>(creatingApi, dataSource, analyticsService, toClean); var update = new UpdateEntityState <TModel, TThreadsafe>(updatingApi, dataSource, analyticsService, toClean); var delete = new DeleteEntityState <TModel, TDatabase, TThreadsafe>(deletingApi, dataSource, analyticsService); var deleteLocal = new DeleteLocalEntityState <TDatabase, TThreadsafe>(dataSource); var tryResolveClientError = new TryResolveClientErrorState <TThreadsafe>(); var unsyncable = new UnsyncableEntityState <TThreadsafe>(dataSource, toUnsyncable); var checkServerStatus = new CheckServerStatusState(api, scheduler, apiDelay, statusDelay, delayCancellation); var finished = new ResetAPIDelayState(apiDelay); transitions.ConfigureTransition(entryPoint, push); transitions.ConfigureTransition(push.PushEntity, pushOne); transitions.ConfigureTransition(pushOne.CreateEntity, create); transitions.ConfigureTransition(pushOne.UpdateEntity, update); transitions.ConfigureTransition(pushOne.DeleteEntity, delete); transitions.ConfigureTransition(pushOne.DeleteEntityLocally, deleteLocal); transitions.ConfigureTransition(create.ClientError, tryResolveClientError); transitions.ConfigureTransition(update.ClientError, tryResolveClientError); transitions.ConfigureTransition(delete.ClientError, tryResolveClientError); transitions.ConfigureTransition(create.ServerError, checkServerStatus); transitions.ConfigureTransition(update.ServerError, checkServerStatus); transitions.ConfigureTransition(delete.ServerError, checkServerStatus); transitions.ConfigureTransition(create.UnknownError, checkServerStatus); transitions.ConfigureTransition(update.UnknownError, checkServerStatus); transitions.ConfigureTransition(delete.UnknownError, checkServerStatus); transitions.ConfigureTransition(tryResolveClientError.UnresolvedTooManyRequests, checkServerStatus); transitions.ConfigureTransition(tryResolveClientError.Unresolved, unsyncable); transitions.ConfigureTransition(checkServerStatus.Retry, checkServerStatus); transitions.ConfigureTransition(checkServerStatus.ServerIsAvailable, push); transitions.ConfigureTransition(create.CreatingFinished, finished); transitions.ConfigureTransition(update.UpdatingSucceeded, finished); transitions.ConfigureTransition(delete.DeletingFinished, finished); transitions.ConfigureTransition(deleteLocal.Deleted, finished); transitions.ConfigureTransition(deleteLocal.DeletingFailed, finished); transitions.ConfigureTransition(finished.Continue, push); return(push.NothingToPush); }
private static void configurePullTransitions( ITransitionConfigurator transitions, ITogglDatabase database, ITogglApi api, ITogglDataSource dataSource, ITimeService timeService, IAnalyticsService analyticsService, IScheduler scheduler, StateResult entryPoint, ILeakyBucket leakyBucket, IRateLimiter rateLimiter, ISyncStateQueue queue) { var delayState = new WaitForAWhileState(scheduler, analyticsService); var fetchAllSince = new FetchAllSinceState(api, database.SinceParameters, timeService, leakyBucket, rateLimiter); var ensureFetchWorkspacesSucceeded = new EnsureFetchListSucceededState <IWorkspace>(); var ensureFetchWorkspaceFeaturesSucceeded = new EnsureFetchListSucceededState <IWorkspaceFeatureCollection>(); var ensureFetchTagsSucceeded = new EnsureFetchListSucceededState <ITag>(); var ensureFetchClientsSucceeded = new EnsureFetchListSucceededState <IClient>(); var ensureFetchProjectsSucceeded = new EnsureFetchListSucceededState <IProject>(); var ensureFetchTasksSucceeded = new EnsureFetchListSucceededState <ITask>(); var ensureFetchTimeEntriesSucceeded = new EnsureFetchListSucceededState <ITimeEntry>(); var ensureFetchUserSucceeded = new EnsureFetchSingletonSucceededState <IUser>(); var ensureFetchPreferencesSucceeded = new EnsureFetchSingletonSucceededState <IPreferences>(); var scheduleCleanUp = new ScheduleCleanUpState(queue); var detectGainingAccessToWorkspaces = new DetectGainingAccessToWorkspacesState( dataSource.Workspaces, analyticsService, () => new HasFinsihedSyncBeforeInteractor(dataSource)); var resetSinceParams = new ResetSinceParamsState(database.SinceParameters); var persistNewWorkspaces = new PersistNewWorkspacesState(dataSource.Workspaces); var detectLosingAccessToWorkspaces = new DetectLosingAccessToWorkspacesState(dataSource.Workspaces, analyticsService); var deleteRunningInaccessibleTimeEntry = new DeleteInaccessibleRunningTimeEntryState(dataSource.TimeEntries); var markWorkspacesAsInaccessible = new MarkWorkspacesAsInaccessibleState(dataSource.Workspaces); var persistWorkspaces = new PersistListState <IWorkspace, IDatabaseWorkspace, IThreadSafeWorkspace>(dataSource.Workspaces, Workspace.Clean); var updateWorkspacesSinceDate = new UpdateSinceDateState <IWorkspace>(database.SinceParameters); var detectNoWorkspaceState = new DetectNotHavingAccessToAnyWorkspaceState(dataSource); var persistWorkspaceFeatures = new PersistListState <IWorkspaceFeatureCollection, IDatabaseWorkspaceFeatureCollection, IThreadSafeWorkspaceFeatureCollection>( dataSource.WorkspaceFeatures, WorkspaceFeatureCollection.From); var persistUser = new PersistSingletonState <IUser, IDatabaseUser, IThreadSafeUser>(dataSource.User, User.Clean); var noDefaultWorkspaceDetectingState = new DetectUserHavingNoDefaultWorkspaceSetState(dataSource, analyticsService); var trySetDefaultWorkspaceState = new TrySetDefaultWorkspaceState(timeService, dataSource); var persistTags = new PersistListState <ITag, IDatabaseTag, IThreadSafeTag>(dataSource.Tags, Tag.Clean); var updateTagsSinceDate = new UpdateSinceDateState <ITag>(database.SinceParameters); var persistClients = new PersistListState <IClient, IDatabaseClient, IThreadSafeClient>(dataSource.Clients, Client.Clean); var updateClientsSinceDate = new UpdateSinceDateState <IClient>(database.SinceParameters); var persistPreferences = new PersistSingletonState <IPreferences, IDatabasePreferences, IThreadSafePreferences>(dataSource.Preferences, Preferences.Clean); var persistProjects = new PersistListState <IProject, IDatabaseProject, IThreadSafeProject>(dataSource.Projects, Project.Clean); var updateProjectsSinceDate = new UpdateSinceDateState <IProject>(database.SinceParameters); var createProjectPlaceholders = new CreateArchivedProjectPlaceholdersState(dataSource.Projects, analyticsService); var persistTimeEntries = new PersistListState <ITimeEntry, IDatabaseTimeEntry, IThreadSafeTimeEntry>(dataSource.TimeEntries, TimeEntry.Clean); var updateTimeEntriesSinceDate = new UpdateSinceDateState <ITimeEntry>(database.SinceParameters); var persistTasks = new PersistListState <ITask, IDatabaseTask, IThreadSafeTask>(dataSource.Tasks, Task.Clean); var updateTasksSinceDate = new UpdateSinceDateState <ITask>(database.SinceParameters); var refetchInaccessibleProjects = new TryFetchInaccessibleProjectsState(dataSource.Projects, timeService, api.Projects); // start all the API requests first transitions.ConfigureTransition(entryPoint, fetchAllSince); // prevent overloading server with too many requests transitions.ConfigureTransition(fetchAllSince.PreventOverloadingServer, delayState); // detect gaining access to workspaces transitions.ConfigureTransition(fetchAllSince.Done, ensureFetchWorkspacesSucceeded); transitions.ConfigureTransition(ensureFetchWorkspacesSucceeded.Done, detectGainingAccessToWorkspaces); transitions.ConfigureTransition(detectGainingAccessToWorkspaces.Done, detectLosingAccessToWorkspaces); transitions.ConfigureTransition(detectGainingAccessToWorkspaces.NewWorkspacesDetected, resetSinceParams); transitions.ConfigureTransition(resetSinceParams.Done, persistNewWorkspaces); transitions.ConfigureTransition(persistNewWorkspaces.Done, fetchAllSince); // detect losing access to workspaces transitions.ConfigureTransition(detectLosingAccessToWorkspaces.Done, persistWorkspaces); transitions.ConfigureTransition(detectLosingAccessToWorkspaces.WorkspaceAccessLost, markWorkspacesAsInaccessible); transitions.ConfigureTransition(markWorkspacesAsInaccessible.Done, scheduleCleanUp); transitions.ConfigureTransition(scheduleCleanUp.Done, deleteRunningInaccessibleTimeEntry); transitions.ConfigureTransition(deleteRunningInaccessibleTimeEntry.Done, persistWorkspaces); // persist all the data pulled from the server transitions.ConfigureTransition(persistWorkspaces.Done, updateWorkspacesSinceDate); transitions.ConfigureTransition(updateWorkspacesSinceDate.Done, detectNoWorkspaceState); transitions.ConfigureTransition(detectNoWorkspaceState.Done, ensureFetchUserSucceeded); transitions.ConfigureTransition(ensureFetchUserSucceeded.Done, persistUser); transitions.ConfigureTransition(persistUser.Done, ensureFetchWorkspaceFeaturesSucceeded); transitions.ConfigureTransition(ensureFetchWorkspaceFeaturesSucceeded.Done, persistWorkspaceFeatures); transitions.ConfigureTransition(persistWorkspaceFeatures.Done, ensureFetchPreferencesSucceeded); transitions.ConfigureTransition(ensureFetchPreferencesSucceeded.Done, persistPreferences); transitions.ConfigureTransition(persistPreferences.Done, ensureFetchTagsSucceeded); transitions.ConfigureTransition(ensureFetchTagsSucceeded.Done, persistTags); transitions.ConfigureTransition(persistTags.Done, updateTagsSinceDate); transitions.ConfigureTransition(updateTagsSinceDate.Done, ensureFetchClientsSucceeded); transitions.ConfigureTransition(ensureFetchClientsSucceeded.Done, persistClients); transitions.ConfigureTransition(persistClients.Done, updateClientsSinceDate); transitions.ConfigureTransition(updateClientsSinceDate.Done, ensureFetchProjectsSucceeded); transitions.ConfigureTransition(ensureFetchProjectsSucceeded.Done, persistProjects); transitions.ConfigureTransition(persistProjects.Done, updateProjectsSinceDate); transitions.ConfigureTransition(updateProjectsSinceDate.Done, ensureFetchTasksSucceeded); transitions.ConfigureTransition(ensureFetchTasksSucceeded.Done, persistTasks); transitions.ConfigureTransition(persistTasks.Done, updateTasksSinceDate); transitions.ConfigureTransition(updateTasksSinceDate.Done, ensureFetchTimeEntriesSucceeded); transitions.ConfigureTransition(ensureFetchTimeEntriesSucceeded.Done, createProjectPlaceholders); transitions.ConfigureTransition(createProjectPlaceholders.Done, persistTimeEntries); transitions.ConfigureTransition(persistTimeEntries.Done, updateTimeEntriesSinceDate); transitions.ConfigureTransition(updateTimeEntriesSinceDate.Done, refetchInaccessibleProjects); transitions.ConfigureTransition(refetchInaccessibleProjects.FetchNext, refetchInaccessibleProjects); transitions.ConfigureTransition(refetchInaccessibleProjects.Done, noDefaultWorkspaceDetectingState); transitions.ConfigureTransition(noDefaultWorkspaceDetectingState.NoDefaultWorkspaceDetected, trySetDefaultWorkspaceState); transitions.ConfigureTransition(noDefaultWorkspaceDetectingState.Done, new DeadEndState()); transitions.ConfigureTransition(trySetDefaultWorkspaceState.Done, new DeadEndState()); // fail for server errors transitions.ConfigureTransition(ensureFetchWorkspacesSucceeded.ErrorOccured, new FailureState()); transitions.ConfigureTransition(ensureFetchUserSucceeded.ErrorOccured, new FailureState()); transitions.ConfigureTransition(ensureFetchWorkspaceFeaturesSucceeded.ErrorOccured, new FailureState()); transitions.ConfigureTransition(ensureFetchPreferencesSucceeded.ErrorOccured, new FailureState()); transitions.ConfigureTransition(ensureFetchTagsSucceeded.ErrorOccured, new FailureState()); transitions.ConfigureTransition(ensureFetchClientsSucceeded.ErrorOccured, new FailureState()); transitions.ConfigureTransition(ensureFetchProjectsSucceeded.ErrorOccured, new FailureState()); transitions.ConfigureTransition(ensureFetchTasksSucceeded.ErrorOccured, new FailureState()); transitions.ConfigureTransition(ensureFetchTimeEntriesSucceeded.ErrorOccured, new FailureState()); transitions.ConfigureTransition(refetchInaccessibleProjects.ErrorOccured, new FailureState()); // delay loop transitions.ConfigureTransition(delayState.Done, fetchAllSince); }
private static LookForSingletonChangeToPushState <TThreadsafe> configurePushSingleton <TModel, TThreadsafe>( ITransitionConfigurator transitions, IStateResult entryPoint, ISingletonDataSource <TThreadsafe> dataSource, IAnalyticsService analyticsService, IUpdatingApiClient <TModel> updatingApi, ILeakyBucket minutesLeakyBucket, IRateLimiter rateLimiter, WaitForAWhileState waitForAWhileState, Func <TModel, TThreadsafe> toClean, Func <TThreadsafe, string, TThreadsafe> toUnsyncable) where TModel : class where TThreadsafe : class, TModel, IThreadSafeModel, IDatabaseSyncable, IIdentifiable { var lookForChange = new LookForSingletonChangeToPushState <TThreadsafe>(dataSource); var chooseOperation = new ChooseSyncOperationState <TThreadsafe>(); var update = new UpdateEntityState <TModel, TThreadsafe>(updatingApi, dataSource, analyticsService, minutesLeakyBucket, rateLimiter, toClean); var processClientError = new ProcessClientErrorState <TThreadsafe>(); var unsyncable = new MarkEntityAsUnsyncableState <TThreadsafe>(dataSource, toUnsyncable); transitions.ConfigureTransition(entryPoint, lookForChange); transitions.ConfigureTransition(lookForChange.ChangeFound, chooseOperation); transitions.ConfigureTransition(chooseOperation.UpdateEntity, update); transitions.ConfigureTransition(chooseOperation.CreateEntity, new InvalidTransitionState($"Creating is not supported for {typeof(TModel).Name} during Push sync.")); transitions.ConfigureTransition(chooseOperation.DeleteEntity, new InvalidTransitionState($"Deleting is not supported for {typeof(TModel).Name} during Push sync.")); transitions.ConfigureTransition(chooseOperation.DeleteEntityLocally, new InvalidTransitionState($"Deleting locally is not supported for {typeof(TModel).Name} during Push sync.")); transitions.ConfigureTransition(update.ClientError, processClientError); transitions.ConfigureTransition(update.ServerError, new FailureState()); transitions.ConfigureTransition(update.UnknownError, new FailureState()); transitions.ConfigureTransition(update.PreventOverloadingServer, waitForAWhileState); transitions.ConfigureTransition(processClientError.UnresolvedTooManyRequests, new FailureState()); transitions.ConfigureTransition(processClientError.Unresolved, unsyncable); transitions.ConfigureTransition(update.Done, lookForChange); transitions.ConfigureTransition(unsyncable.Done, lookForChange); transitions.ConfigureTransition(update.EntityChanged, lookForChange); return(lookForChange); }
private static LookForChangeToPushState <TDatabase, TThreadsafe> configurePush <TModel, TDatabase, TThreadsafe>( ITransitionConfigurator transitions, IStateResult entryPoint, IDataSource <TThreadsafe, TDatabase> dataSource, IAnalyticsService analyticsService, ICreatingApiClient <TModel> creatingApi, IUpdatingApiClient <TModel> updatingApi, IDeletingApiClient <TModel> deletingApi, ILeakyBucket minutesLeakyBucket, IRateLimiter rateLimiter, WaitForAWhileState waitForAWhileState, Func <TModel, TThreadsafe> toClean, Func <TThreadsafe, string, TThreadsafe> toUnsyncable) where TModel : class, IIdentifiable, ILastChangedDatable where TDatabase : class, TModel, IDatabaseSyncable where TThreadsafe : class, TDatabase, IThreadSafeModel { var lookForChange = new LookForChangeToPushState <TDatabase, TThreadsafe>(dataSource); var chooseOperation = new ChooseSyncOperationState <TThreadsafe>(); var create = new CreateEntityState <TModel, TDatabase, TThreadsafe>(creatingApi, dataSource, analyticsService, minutesLeakyBucket, rateLimiter, toClean); var update = new UpdateEntityState <TModel, TThreadsafe>(updatingApi, dataSource, analyticsService, minutesLeakyBucket, rateLimiter, toClean); var delete = new DeleteEntityState <TModel, TDatabase, TThreadsafe>(deletingApi, analyticsService, dataSource, minutesLeakyBucket, rateLimiter); var deleteLocal = new DeleteLocalEntityState <TDatabase, TThreadsafe>(dataSource); var processClientError = new ProcessClientErrorState <TThreadsafe>(); var unsyncable = new MarkEntityAsUnsyncableState <TThreadsafe>(dataSource, toUnsyncable); transitions.ConfigureTransition(entryPoint, lookForChange); transitions.ConfigureTransition(lookForChange.ChangeFound, chooseOperation); transitions.ConfigureTransition(chooseOperation.CreateEntity, create); transitions.ConfigureTransition(chooseOperation.UpdateEntity, update); transitions.ConfigureTransition(chooseOperation.DeleteEntity, delete); transitions.ConfigureTransition(chooseOperation.DeleteEntityLocally, deleteLocal); transitions.ConfigureTransition(create.ClientError, processClientError); transitions.ConfigureTransition(update.ClientError, processClientError); transitions.ConfigureTransition(delete.ClientError, processClientError); transitions.ConfigureTransition(create.ServerError, new FailureState()); transitions.ConfigureTransition(update.ServerError, new FailureState()); transitions.ConfigureTransition(delete.ServerError, new FailureState()); transitions.ConfigureTransition(create.UnknownError, new FailureState()); transitions.ConfigureTransition(update.UnknownError, new FailureState()); transitions.ConfigureTransition(delete.UnknownError, new FailureState()); transitions.ConfigureTransition(processClientError.UnresolvedTooManyRequests, new FailureState()); transitions.ConfigureTransition(processClientError.Unresolved, unsyncable); transitions.ConfigureTransition(create.EntityChanged, lookForChange); transitions.ConfigureTransition(update.EntityChanged, lookForChange); transitions.ConfigureTransition(create.PreventOverloadingServer, waitForAWhileState); transitions.ConfigureTransition(update.PreventOverloadingServer, waitForAWhileState); transitions.ConfigureTransition(delete.PreventOverloadingServer, waitForAWhileState); transitions.ConfigureTransition(create.Done, lookForChange); transitions.ConfigureTransition(update.Done, lookForChange); transitions.ConfigureTransition(delete.Done, lookForChange); transitions.ConfigureTransition(deleteLocal.Done, lookForChange); transitions.ConfigureTransition(deleteLocal.DeletingFailed, lookForChange); transitions.ConfigureTransition(unsyncable.Done, lookForChange); return(lookForChange); }
private static void configureCleanUpTransitions( ITransitionConfigurator transitions, ITimeService timeService, ITogglDataSource dataSource, IAnalyticsService analyticsService, StateResult entryPoint) { var deleteOlderEntries = new DeleteOldTimeEntriesState(timeService, dataSource.TimeEntries); var deleteUnsnecessaryProjectPlaceholders = new DeleteUnnecessaryProjectPlaceholdersState(dataSource.Projects, dataSource.TimeEntries); var deleteInaccessibleTimeEntries = new DeleteInaccessibleTimeEntriesState(dataSource.TimeEntries); var deleteInaccessibleTags = new DeleteNonReferencedInaccessibleTagsState(dataSource.Tags, dataSource.TimeEntries); var deleteInaccessibleTasks = new DeleteNonReferencedInaccessibleTasksState(dataSource.Tasks, dataSource.TimeEntries); var deleteInaccessibleProjects = new DeleteNonReferencedInaccessibleProjectsState(dataSource.Projects, dataSource.Tasks, dataSource.TimeEntries); var deleteInaccessibleClients = new DeleteNonReferencedInaccessibleClientsState(dataSource.Clients, dataSource.Projects); var deleteInaccessibleWorkspaces = new DeleteNonReferencedInaccessibleWorkspacesState( dataSource.Workspaces, dataSource.TimeEntries, dataSource.Projects, dataSource.Tasks, dataSource.Clients, dataSource.Tags); var trackInaccesssibleDataAfterCleanUp = new TrackInaccessibleDataAfterCleanUpState(dataSource, analyticsService); var trackInaccesssibleWorkspacesAfterCleanUp = new TrackInaccessibleWorkspacesAfterCleanUpState(dataSource, analyticsService); transitions.ConfigureTransition(entryPoint, deleteOlderEntries); transitions.ConfigureTransition(deleteOlderEntries.Done, deleteUnsnecessaryProjectPlaceholders); transitions.ConfigureTransition(deleteUnsnecessaryProjectPlaceholders.Done, deleteInaccessibleTimeEntries); transitions.ConfigureTransition(deleteInaccessibleTimeEntries.Done, deleteInaccessibleTags); transitions.ConfigureTransition(deleteInaccessibleTags.Done, deleteInaccessibleTasks); transitions.ConfigureTransition(deleteInaccessibleTasks.Done, deleteInaccessibleProjects); transitions.ConfigureTransition(deleteInaccessibleProjects.Done, deleteInaccessibleClients); transitions.ConfigureTransition(deleteInaccessibleClients.Done, trackInaccesssibleDataAfterCleanUp); transitions.ConfigureTransition(trackInaccesssibleDataAfterCleanUp.Done, deleteInaccessibleWorkspaces); transitions.ConfigureTransition(deleteInaccessibleWorkspaces.Done, trackInaccesssibleWorkspacesAfterCleanUp); transitions.ConfigureTransition(trackInaccesssibleWorkspacesAfterCleanUp.Done, new DeadEndState()); }
private static void configurePullTimeEntriesTransitions( ITransitionConfigurator transitions, ITogglApi api, ITogglDataSource dataSource, ITogglDatabase database, IAnalyticsService analyticsService, ITimeService timeService, ILeakyBucket leakyBucket, IRateLimiter rateLimiter, ILastTimeUsageStorage lastTimeUsageStorage, StateResult entryPoint) { var fetchTimeEntries = new FetchJustTimeEntriesSinceState(api, database.SinceParameters, timeService, leakyBucket, rateLimiter); var ensureFetchTimeEntriesSucceeded = new EnsureFetchListSucceededState <ITimeEntry>(); var placeholderStateFactory = new CreatePlaceholdersStateFactory( dataSource, analyticsService, lastTimeUsageStorage, timeService); var createWorkspacePlaceholder = placeholderStateFactory.ForWorkspaces(); var createProjectPlaceholder = placeholderStateFactory.ForProjects(); var createTaskPlaceholder = placeholderStateFactory.ForTasks(); var createTagPlaceholder = placeholderStateFactory.ForTags(); var persistTimeEntries = new PersistListState <ITimeEntry, IDatabaseTimeEntry, IThreadSafeTimeEntry>(dataSource.TimeEntries, TimeEntry.Clean); var updateTimeEntriesSinceDate = new UpdateSinceDateState <ITimeEntry>(database.SinceParameters); transitions.ConfigureTransition(entryPoint, fetchTimeEntries); transitions.ConfigureTransition(fetchTimeEntries.PreventOverloadingServer, new DeadEndState()); transitions.ConfigureTransition(fetchTimeEntries.Done, ensureFetchTimeEntriesSucceeded); transitions.ConfigureTransition(ensureFetchTimeEntriesSucceeded.ErrorOccured, new FailureState()); transitions.ConfigureTransition(ensureFetchTimeEntriesSucceeded.Done, createWorkspacePlaceholder); transitions.ConfigureTransition(createWorkspacePlaceholder.Done, createProjectPlaceholder); transitions.ConfigureTransition(createProjectPlaceholder.Done, createTaskPlaceholder); transitions.ConfigureTransition(createTaskPlaceholder.Done, createTagPlaceholder); transitions.ConfigureTransition(createTagPlaceholder.Done, persistTimeEntries); transitions.ConfigureTransition(persistTimeEntries.Done, updateTimeEntriesSinceDate); transitions.ConfigureTransition(updateTimeEntriesSinceDate.Done, new DeadEndState()); }