public LanguageExt.Unit SetData(long time, SessionId sessionId, string key, object value) { var added = false; Sync.SetData(sessionId, key, value, time); cluster.Iter(c => { added = c.HashFieldAddOrUpdateIfKeyExists(SessionKey(sessionId), key, SessionDataItemDTO.Create(value)); if (added && key == SupplementarySessionId.Key && value is SupplementarySessionId supp) { SupplementarySessionManager.setSuppSessionInSuppMap(c, sessionId, supp); } }); return(added ? cluster.Iter(c => c.PublishToChannel(SessionsNotify, SessionAction.SetData( time, sessionId, key, value, system, nodeName))) : unit); }
public LanguageExt.Unit Stop(SessionId sessionId) { Sync.Stop(sessionId); cluster.Iter(c => { c.Delete(SessionKey(sessionId)); SupplementarySessionManager.removeSessionIdFromSuppMap(c, sessionId); }); return(cluster.Iter(c => c.PublishToChannel(SessionsNotify, SessionAction.Stop(sessionId, system, nodeName)))); }
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); } }); }); }
public LanguageExt.Unit ClearData(long time, SessionId sessionId, string key) { Sync.ClearData(sessionId, key, time); cluster.Iter(c => { c.DeleteHashField(SessionKey(sessionId), key); if (key == SupplementarySessionId.Key) { SupplementarySessionManager.removeSessionIdFromSuppMap(c, sessionId); } }); return(cluster.Iter(c => c.PublishToChannel( SessionsNotify, SessionAction.ClearData(time, sessionId, key, system, nodeName)))); }
Option <SessionId> getSessionIdFromCluster(SupplementarySessionId suppSessionId) => from c in cluster from s in SupplementarySessionManager.getSessionIdFromSuppMap(c, suppSessionId) from to in c.GetHashField <int>(SessionKey(s), TimeoutKey) let _ = Sync.UpdateSupplementarySessionId(s, suppSessionId) select Sync.Start(s, to);