public ValueVector AddValue(long time, object value, VectorConflictStrategy strategy)
        {
            if(Vector.Count == 0 || time > Time)
            {
                return new ValueVector(time, List(value));
            }

            if( time < Time)
            {
                // A value from the past has arrived, we're going to drop it because
                // we've already moved on.
                return this;
            }

            if (Vector.Exists(x => x.Equals(value)))
            {
                // There's already an entry at the same time with the
                // same value
                return this;
            }
            else
            {
                // Conflict!
                switch(strategy)
                {
                    case VectorConflictStrategy.First:  return this;
                    case VectorConflictStrategy.Last:   return new ValueVector(time, List(value));
                    case VectorConflictStrategy.Branch: return new ValueVector(Time, Vector.Add(value));
                    default: throw new ArgumentException("VectorConflictStrategy not supported: " + strategy);
                }
            }
        }
        public ValueVector AddValue(long time, object value, VectorConflictStrategy strategy)
        {
            if (Vector.Count == 0 || time > Time)
            {
                return(new ValueVector(time, List(value)));
            }

            if (time < Time)
            {
                // A value from the past has arrived, we're going to drop it because
                // we've already moved on.
                return(this);
            }

            if (Vector.Exists(x => x.Equals(value)))
            {
                // There's already an entry at the same time with the
                // same value
                return(this);
            }
            else
            {
                // Conflict!
                switch (strategy)
                {
                case VectorConflictStrategy.First:  return(this);

                case VectorConflictStrategy.Last:   return(new ValueVector(time, List(value)));

                case VectorConflictStrategy.Branch: return(new ValueVector(Time, Vector.Add(value)));

                default: throw new ArgumentException("VectorConflictStrategy not supported: " + strategy);
                }
            }
        }
 /// <summary>
 /// Add or update a key in the session key/value store
 /// </summary>
 public void SetKeyValue(long time, string key, object value, VectorConflictStrategy strategy)
 {
     lock (sync)
     {
         data = data.Find(key)
                .Map(vector => data.AddOrUpdate(key, vector.AddValue(time, value, strategy)))
                .IfNone(() => data.AddOrUpdate(key, new ValueVector(time, List(value))));
     }
     Touch();
 }
Exemple #4
0
 /// <summary>
 /// Add or update a key in the session key/value store
 /// </summary>
 public void SetKeyValue(long time, string key, object value, VectorConflictStrategy strategy)
 {
     lock (sync)
     {
         data = (from d      in data.Find(key)
                 from vector in d.ToOption()
                 select data.AddOrUpdate(key, vector.AddValue(time, value, strategy)))
                .IfNone(() => data.AddOrUpdate(key, ValueVector.New(time, value)));
     }
     Touch();
 }
        public SessionManager(Option<ICluster> cluster, SystemName system, ProcessName nodeName, VectorConflictStrategy strategy)
        {
            this.cluster = cluster;
            this.system = system;
            this.nodeName = nodeName;

            Sync = new SessionSync(system, nodeName, strategy);

            cluster.Iter(c =>
            {
                notify = c.SubscribeToChannel<SessionAction>(SessionsNotify).Subscribe(act => Sync.Incoming(act));

                var now = DateTime.UtcNow;

                // Look for stranded sessions that haven't been removed properly.  This is done once only
                // on startup because the systems should be shutting down sessions on their own.  This just
                // catches the situation where an app-domain died without shutting down properly.
                c.QuerySessionKeys()
                 .Map(key =>
                    from ts in c.GetHashField<long>(key, LastAccessKey)
                    from to in c.GetHashField<int>(key, TimeoutKey)
                    where new DateTime(ts) < now.AddSeconds(to * 2) // Multiply by 2, just to catch genuine non-active sessions
                    select c.Delete(key))
                 .Iter(id => { });

                // Remove session keys when an in-memory session ends
                ended = SessionEnded.Subscribe(sid => Stop(sid));

                touch = Sync.Touched.Subscribe(tup =>
                {
                    try
                    {
                        c.HashFieldAddOrUpdate(SessionKey(tup.Item1), LastAccessKey, DateTime.UtcNow.Ticks);
                        c.PublishToChannel(SessionsNotify, SessionAction.Touch(tup.Item1, system, nodeName));
                    }
                    catch(Exception e)
                    {
                        logErr(e);
                    }
                });
            });
        }
 public static SessionVector Create(int timeout, VectorConflictStrategy strategy, Map<string,object> initialState) =>
     new SessionVector(Map.empty<string, ValueVector>(), DateTime.UtcNow, timeout, initialState);
 /// <summary>
 /// Add or update a key in the session key/value store
 /// </summary>
 public void SetKeyValue(long time, string key, object value, VectorConflictStrategy strategy)
 {
     lock (sync)
     {
         data = data.Find(key)
                    .Map(vector => data.AddOrUpdate(key, vector.AddValue(time, value, strategy)))
                    .IfNone(() => data.AddOrUpdate(key, new ValueVector(time, List(value))));
     }
     Touch();
 }
Exemple #8
0
 public SessionSync(SystemName system, ProcessName nodeName, VectorConflictStrategy strategy)
 {
     this.system   = system;
     this.nodeName = nodeName;
     this.strategy = strategy;
 }
 public static SessionVector Create(int timeout, VectorConflictStrategy strategy, Map <string, object> initialState) =>
 new SessionVector(Map.empty <string, ValueVector>(), DateTime.UtcNow, timeout, initialState);
Exemple #10
0
        public SessionManager(Option <ICluster> cluster, SystemName system, ProcessName nodeName, VectorConflictStrategy strategy)
        {
            this.cluster  = cluster;
            this.system   = system;
            this.nodeName = nodeName;

            Sync = new SessionSync(system, nodeName, strategy);

            cluster.Iter(c =>
            {
                notify = c.SubscribeToChannel <SessionAction>(SessionsNotify).Subscribe(act => Sync.Incoming(act));

                var now = DateTime.UtcNow;

                // Look for stranded sessions that haven't been removed properly.  This is done once only
                // on startup because the systems should be shutting down sessions on their own.  This just
                // catches the situation where an app-domain died without shutting down properly.
                c.GetAllHashFieldsInBatch(c.QuerySessionKeys().ToSeq())
                .Map(sessions =>
                     sessions.Filter(vals => (from ts in vals.Find(LastAccessKey).Map(v => new DateTime((long)v))
                                              from to in vals.Find(TimeoutKey).Map(v => (long)v)
                                              where ts < now.AddSeconds(-to * 2)
                                              select true).IfNone(false))
                     .Keys)
                .Map(Seq)
                .Do(strandedSessions => SupplementarySessionManager.removeSessionIdFromSuppMap(c, strandedSessions.Map(ReverseSessionKey)))
                .Do(strandedSessions => c.DeleteMany(strandedSessions))
                .Map(strandedSessions => strandedSessions.Iter(sessionId => c.PublishToChannel(SessionsNotify, SessionAction.Stop(sessionId, system, nodeName))));;



                // Remove session keys when an in-memory session ends
                ended = SessionEnded.Subscribe(sid => Stop(sid));

                touch = Sync.Touched.Subscribe(tup =>
                {
                    try
                    {
                        //check if the session has not been stopped in the meantime or expired
                        if (c.HashFieldAddOrUpdateIfKeyExists(SessionKey(tup.Item1), LastAccessKey, DateTime.UtcNow.Ticks))
                        {
                            c.PublishToChannel(SessionsNotify, SessionAction.Touch(tup.Item1, system, nodeName));
                        }
                    }
                    catch (Exception e)
                    {
                        logErr(e);
                    }
                });
            });
        }
Exemple #11
0
 public static SessionVector Create(int timeout, VectorConflictStrategy strategy) =>
 new SessionVector(DateTime.UtcNow, timeout);
        public SessionManager(Option <ICluster> cluster, SystemName system, ProcessName nodeName, VectorConflictStrategy strategy)
        {
            this.cluster  = cluster;
            this.system   = system;
            this.nodeName = nodeName;

            Sync = new SessionSync(system, nodeName, strategy);

            cluster.Iter(c =>
            {
                notify = c.SubscribeToChannel <SessionAction>(SessionsNotify).Subscribe(act => Sync.Incoming(act));

                var now = DateTime.UtcNow;

                // Look for stranded sessions that haven't been removed properly.  This is done once only
                // on startup because the systems should be shutting down sessions on their own.  This just
                // catches the situation where an app-domain died without shutting down properly.
                c.QuerySessionKeys()
                .Map(key =>
                     from ts in c.GetHashField <long>(key, LastAccessKey)
                     from to in c.GetHashField <int>(key, TimeoutKey)
                     where new DateTime(ts) < now.AddSeconds(-to * 2) // Multiply by 2, just to catch genuine non-active sessions
                     select c.Delete(key))
                .Iter(id => { });

                // Remove session keys when an in-memory session ends
                ended = SessionEnded.Subscribe(sid => Stop(sid));

                touch = Sync.Touched.Subscribe(tup =>
                {
                    try
                    {
                        c.HashFieldAddOrUpdate(SessionKey(tup.Item1), LastAccessKey, DateTime.UtcNow.Ticks);
                        c.PublishToChannel(SessionsNotify, SessionAction.Touch(tup.Item1, system, nodeName));
                    }
                    catch (Exception e)
                    {
                        logErr(e);
                    }
                });
            });
        }
 public SessionSync(SystemName system, ProcessName nodeName, VectorConflictStrategy strategy)
 {
     this.system = system;
     this.nodeName = nodeName;
     this.strategy = strategy;
 }