// // Copyright 2014-2015 Amazon.com, // Inc. or its affiliates. All Rights Reserved. // // SPDX-License-Identifier: Apache-2.0 // using Amazon.Runtime; using Amazon.Runtime.Internal; using Amazon.Runtime.Internal.Util; using Amazon.Util.Internal; using Amazon.Util.Internal.PlatformServices; using System; using System.Collections.Generic; using System.Threading; namespace Amazon.CognitoSync.SyncManager { public partial class Dataset : IDisposable { INetworkReachability _netReachability; private AsyncOptions OnConnectivityOptions = null; /// /// Synchronize between local storage and remote storage. /// /// Amazon Cognito Sync Dev. Guide - Synchronizing Local Data with the Sync Store public virtual void SynchronizeAsync(AsyncOptions options = null) { options = options == null ? new AsyncOptions() : options; if (_netReachability.NetworkStatus == NetworkStatus.NotReachable) { FireSyncFailureEvent(new NetworkException("Network connectivity unavailable."), options); return; } SynchronizeHelperAsync(options); } private void DatasetSetupInternal() { _netReachability = ServiceFactory.Instance.GetService(); _netReachability.NetworkReachabilityChanged += OnNetworkReachabilityChanged; } /// /// Attempt to synchronize when connectivity is available. If /// the connectivity is available right away, it behaves the same as /// . Otherwise it listens to connectivity /// changes, and will do a sync once the connectivity is back. Note that if /// this method is called multiple times, only the last synchronize request /// is kept. If either the dataset or the callback is garbage collected /// , this method will not perform a sync and the callback won't fire. /// public virtual void SynchronizeOnConnectivity(AsyncOptions options = null) { if (_netReachability.NetworkStatus != NetworkStatus.NotReachable) { SynchronizeAsync(options); } else { waitingForConnectivity = true; OnConnectivityOptions = options; } } private void OnNetworkReachabilityChanged(object sender, NetworkStatusEventArgs e) { if (!waitingForConnectivity) { return; } if (e.Status != NetworkStatus.NotReachable) { var options = OnConnectivityOptions; OnConnectivityOptions = null; SynchronizeAsync(options); } } /// /// Releases the resources consumed by this object if disposing is true. /// protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { ClearAllDelegates(); _netReachability.NetworkReachabilityChanged -= OnNetworkReachabilityChanged; _disposed = true; } } private void SynchronizeHelperAsync(AsyncOptions options) { try { if (locked) { _logger.InfoFormat("Already in a Synchronize. Queueing new request.", DatasetName); queuedSync = true; return; } else { locked = true; } waitingForConnectivity = false; InternalSDKUtils.AsyncExecutor(() => { //make sure we have the updated credentials; SynchornizeInternal(options); }, new AsyncOptions() { ExecuteCallbackOnMainThread = false }); } catch (Exception e) { FireSyncFailureEvent(e, options); _logger.Error(e, ""); } } /// /// Fires a Sync Success Event /// /// List of records after successful sync /// AsyncOptions object that controls whether protected void FireSyncSuccessEvent(List records, AsyncOptions options) { if (options.ExecuteCallbackOnMainThread) { // Enqueue the callback so that the Unity main thread dispatcher // can invoke the callback on the main thread. UnityRequestQueue.Instance.ExecuteOnMainThread(() => { FireSyncSuccessEvent(records); }); } else { FireSyncSuccessEvent(records); } } /// /// Fires a Sync Failure event. /// /// Exception object which caused the sync Failure /// AsyncOptions object that controls whether protected void FireSyncFailureEvent(Exception exception, AsyncOptions options) { if (options.ExecuteCallbackOnMainThread) { // Enqueue the callback so that the Unity main thread dispatcher // can invoke the callback on the main thread. UnityRequestQueue.Instance.ExecuteOnMainThread(() => { FireSyncFailureEvent(exception); }); } else { FireSyncFailureEvent(exception); } } } }