Example #1
0
        internal async Task OnBackgroundModeChangedAsync(object sender, BackgroundModeChangedEventArgs args)
        {
            var goingIntoBackground = args.IsInBackground;
            var wasInBackground     = LockUtils.WithWriteLock(_stateLock, () =>
            {
                var oldValue  = _inBackground;
                _inBackground = goingIntoBackground;
                return(oldValue);
            });

            if (goingIntoBackground == wasInBackground)
            {
                return;
            }
            Log.DebugFormat("Background mode is changing to {0}", goingIntoBackground);
            if (goingIntoBackground)
            {
                if (!Config.EnableBackgroundUpdating)
                {
                    Log.Debug("Background updating is disabled");
                    await _connectionManager.SetUpdateProcessorFactory(null, false);

                    return;
                }
                Log.Debug("Background updating is enabled, starting polling processor");
            }
            await _connectionManager.SetUpdateProcessorFactory(
                Factory.CreateUpdateProcessorFactory(_config, User, flagCacheManager, goingIntoBackground),
                false  // don't reset initialized state because the user is still the same
                );
        }
Example #2
0
 /// <summary>
 /// Tells the <c>ConnectionManager</c> that it can go ahead and connect if appropriate.
 /// </summary>
 /// <returns>a task which will yield true if this method results in a successful connection, or
 /// if we are in offline mode and don't need to make a connection</returns>
 public Task <bool> Start()
 {
     return(LockUtils.WithWriteLock(_lock, () =>
     {
         if (_started)
         {
             return Task.FromResult(_initialized);
         }
         _started = true;
         return OpenOrCloseConnectionIfNecessary(); // not awaiting
     }));
 }
Example #3
0
 /// <summary>
 /// Sets whether the client should always be offline, and attempts to connect if appropriate.
 /// </summary>
 /// <remarks>
 /// Besides updating the value of the <see cref="ForceOffline"/> property, we do the
 /// following:
 ///
 /// If <c>forceOffline</c> is true, we drop our current connection (if any), and we will not
 /// make any connections no matter what other properties are changed as long as this property is
 /// still true.
 ///
 /// If <c>forceOffline</c> is false and we already have a connection, nothing happens.
 ///
 /// If <c>forceOffline</c> is false and we have no connection, but other conditions disallow
 /// making a connection (or we do not have an update processor factory), nothing happens.
 ///
 /// If <c>forceOffline</c> is false, and we do not yet have a connection, and no other
 /// conditions disallow making a connection, and we have an update processor factory,
 /// we create an update processor and tell it to start.
 ///
 /// The returned task is immediately completed unless we are making a new connection, in which
 /// case it is completed when the update processor signals success or failure. The task yields
 /// a true result if we successfully made a connection <i>or</i> if we decided not to connect
 /// because we are in offline mode. In other words, the result is true if
 /// <see cref="Initialized"/> is true.
 /// </remarks>
 /// <param name="forceOffline">true if the client should always be offline</param>
 /// <returns>a task as described above</returns>
 public Task <bool> SetForceOffline(bool forceOffline)
 {
     return(LockUtils.WithWriteLock(_lock, () =>
     {
         if (_disposed || _forceOffline == forceOffline)
         {
             return Task.FromResult(false);
         }
         _forceOffline = forceOffline;
         Log.InfoFormat("Offline mode is now {0}", forceOffline);
         return OpenOrCloseConnectionIfNecessary(); // not awaiting
     }));
 }
Example #4
0
 /// <summary>
 /// Sets whether we should be able to make network connections, and attempts to connect if appropriate.
 /// </summary>
 /// <remarks>
 /// Besides updating the value of the <see cref="NetworkEnabled"/> property, we do the
 /// following:
 ///
 /// If <c>networkEnabled</c> is false, we drop our current connection (if any), and we will not
 /// make any connections no matter what other properties are changed as long as this property is
 /// still true.
 ///
 /// If <c>networkEnabled</c> is true and we already have a connection, nothing happens.
 ///
 /// If <c>networkEnabled</c> is true and we have no connection, but other conditions disallow
 /// making a connection (or we do not have an update processor factory), nothing happens.
 ///
 /// If <c>networkEnabled</c> is true, and we do not yet have a connection, and no other
 /// conditions disallow making a connection, and we have an update processor factory,
 /// we create an update processor and tell it to start.
 ///
 /// The returned task is immediately completed unless we are making a new connection, in which
 /// case it is completed when the update processor signals success or failure. The task yields
 /// a true result if we successfully made a connection <i>or</i> if we decided not to connect
 /// because we are in offline mode. In other words, the result is true if
 /// <see cref="Initialized"/> is true.
 /// </remarks>
 /// <param name="networkEnabled">true if we think we can make network connections</param>
 /// <returns>a task as described above</returns>
 public Task <bool> SetNetworkEnabled(bool networkEnabled)
 {
     return(LockUtils.WithWriteLock(_lock, () =>
     {
         if (_disposed || _networkEnabled == networkEnabled)
         {
             return Task.FromResult(false);
         }
         _networkEnabled = networkEnabled;
         Log.InfoFormat("Network availability is now {0}", networkEnabled);
         return OpenOrCloseConnectionIfNecessary(); // not awaiting
     }));
 }
Example #5
0
        public void Dispose()
        {
            IMobileUpdateProcessor processor = null;

            LockUtils.WithWriteLock(_lock, () =>
            {
                if (_disposed)
                {
                    return;
                }
                processor               = _updateProcessor;
                _updateProcessor        = null;
                _updateProcessorFactory = null;
                _disposed               = true;
            });
            processor?.Dispose();
        }
Example #6
0
 /// <summary>
 /// Sets the factory function for creating an update processor, and attempts to connect if
 /// appropriate.
 /// </summary>
 /// <remarks>
 /// The factory function encapsulates all the information that <see cref="LdClient"/> takes into
 /// account when making a connection, i.e. whether we are in streaming or polling mode, the
 /// polling interval, and the curent user. <c>ConnectionManager</c> itself has no knowledge of
 /// those things.
 ///
 /// Besides updating the private factory function field, we do the following:
 ///
 /// If the function is null, we drop our current connection (if any), and we will not make
 /// any connections no matter what other properties are changed as long as it is still null.
 ///
 /// If it is non-null and we already have the same factory function, nothing happens.
 ///
 /// If it is non-null and we do not already have the same factory function, but other conditions
 /// disallow making a connection, nothing happens.
 ///
 /// If it is non-null and we do not already have the same factory function, and no other
 /// conditions disallow making a connection, we create an update processor and tell it to start.
 /// In this case, we also reset <see cref="Initialized"/> to false if <c>resetInitialized</c> is
 /// true.
 ///
 /// The returned task is immediately completed unless we are making a new connection, in which
 /// case it is completed when the update processor signals success or failure. The task yields
 /// a true result if we successfully made a connection <i>or</i> if we decided not to connect
 /// because we are in offline mode. In other words, the result is true if
 /// <see cref="Initialized"/> is true.
 /// </remarks>
 /// <param name="updateProcessorFactory">a factory function or null</param>
 /// <param name="resetInitialized">true if we should reset the initialized state (e.g. if we
 /// are switching users</param>
 /// <returns>a task as described above</returns>
 public Task <bool> SetUpdateProcessorFactory(Func <IMobileUpdateProcessor> updateProcessorFactory, bool resetInitialized)
 {
     return(LockUtils.WithWriteLock(_lock, () =>
     {
         if (_disposed || _updateProcessorFactory == updateProcessorFactory)
         {
             return Task.FromResult(false);
         }
         _updateProcessorFactory = updateProcessorFactory;
         _updateProcessor?.Dispose();
         _updateProcessor = null;
         if (resetInitialized)
         {
             _initialized = false;
         }
         return OpenOrCloseConnectionIfNecessary(); // not awaiting
     }));
 }
Example #7
0
        /// <inheritdoc/>
        public async Task <bool> IdentifyAsync(User user)
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            User newUser = DecorateUser(user);

            LockUtils.WithWriteLock(_stateLock, () =>
            {
                _user = newUser;
            });

            SendEventIfOnline(_eventFactoryDefault.NewIdentifyEvent(newUser));

            return(await _connectionManager.SetUpdateProcessorFactory(
                       Factory.CreateUpdateProcessorFactory(_config, newUser, flagCacheManager, _inBackground),
                       true
                       ));
        }
Example #8
0
        // When this method is called, we are no longer holding the lock.

        private bool SetInitializedIfUpdateProcessorStartedSuccessfully(Task <bool> task)
        {
            if (task.IsCompleted)
            {
                if (task.IsFaulted)
                {
                    // Don't let exceptions from the update processor propagate up into the SDK. Just say we didn't initialize.
                    Log.ErrorFormat("Failed to initialize LaunchDarkly connection: {0}", Util.ExceptionMessage(task.Exception));
                    return(false);
                }
                var success = task.Result;
                if (success)
                {
                    LockUtils.WithWriteLock(_lock, () =>
                    {
                        _initialized = true;
                    });
                    return(true);
                }
            }
            return(false);
        }