public MessageRecord(MessageMemento message, FactID ancestorFact, RoleMemento ancestorRole, Guid source) { _message = message; _ancestorFact = ancestorFact; _ancestorRole = ancestorRole; _source = source; }
public FactMemento Load(string domain, FactID factId) { IdentifiedFactMemento identifiedMemento = null; using (var session = new Session(_connectionString)) { // Get the fact. session.Command.CommandText = HEAD_SELECT + "WHERE f.FactID = @FactID " + TAIL_JOIN + "ORDER BY p.PredecessorID"; AddParameter(session.Command, "@FactID", factId.key); using (IDataReader reader = session.Command.ExecuteReader()) { session.Command.Parameters.Clear(); identifiedMemento = LoadMementosFromReader(reader).FirstOrDefault(); if (identifiedMemento == null) { throw new CorrespondenceException(string.Format("Unable to find fact {0}", factId.key)); } } } return(identifiedMemento.Memento); }
public void SaveWindowsPhoneSubscriptionIsIdempotent() { Guid gameGuid = Guid.NewGuid(); var game = NewGame(gameGuid); FactID gameId = _repository.Save(TestDomain, game, TestClient); List <FactID> pivotIds = new List <FactID> { gameId }; _repository.SaveWindowsPhoneSubscription( pivotIds, "windows_phone_device_uri", TestClient); _repository.SaveWindowsPhoneSubscription( pivotIds, "windows_phone_device_uri", TestClient); List <WindowsPhoneSubscription> subscriptions = _repository.LoadWindowsPhoneSubscriptions( pivotIds, AnotherClient); Assert.AreEqual(1, subscriptions.Count); Assert.AreEqual(gameId, subscriptions[0].PivotFactId); Assert.AreEqual("windows_phone_device_uri", subscriptions[0].DeviceUri); }
private static FactMemento NewMove(FactID gameId, byte moveIndex) { var move = new FactMemento(MoveType); move.Data = new byte[] { moveIndex }; move.AddPredecessor(MoveGame, gameId, true); return(move); }
public List <FactID> LoadRecentMessages(string domain, FactID pivotId, Guid clientGuid, TimestampID timestamp) { using (var procedures = new Procedures(new Session(_connectionString))) { int clientId = SaveClient(procedures, clientGuid); return(procedures.GetRecentMessages(pivotId, timestamp, clientId)); } }
public void DeleteMessage(FactID ancestorFactId, int ancestorRoleId) { _session.Command.CommandText = "DELETE FROM Message " + "WHERE AncestorFactId = @AncestorFactId AND AncestorRoleId = @AncestorRoleId"; AddParameter("@AncestorFactId", ancestorFactId.key); AddParameter("@AncestorRoleId", ancestorRoleId); _session.Command.ExecuteNonQuery(); _session.Command.Parameters.Clear(); }
public void InsertPredecessor(FactID id, PredecessorMemento predecessor, int roleId) { _session.Command.CommandText = "INSERT Predecessor (FKFactID, FKRoleID, FKPredecessorFactID, IsPivot) VALUES (@FactID, @RoleID, @PredecessorFactID, @IsPivot)"; AddParameter("@FactID", id.key); AddParameter("@RoleID", roleId); AddParameter("@PredecessorFactID", predecessor.ID.key); AddParameter("@IsPivot", predecessor.IsPivot); _session.Command.ExecuteNonQuery(); _session.Command.Parameters.Clear(); }
public void CanLoadAFact() { Guid gameGuid = Guid.NewGuid(); var game = NewGame(gameGuid); FactID gameId = _repository.Save(TestDomain, game, TestClient); var loadedGame = _repository.Load(TestDomain, gameId); Assert.AreEqual(game, loadedGame); }
private void AddToFactTree(string domain, FactTreeMemento messageBody, FactID factId, Dictionary <FactID, FactID> localIdByRemoteId) { if (!messageBody.Contains(factId)) { FactMemento fact = _repository.Load(domain, factId); foreach (PredecessorMemento predecessor in fact.Predecessors) { AddToFactTree(domain, messageBody, predecessor.ID, localIdByRemoteId); } messageBody.Add(new IdentifiedFactMemento(factId, fact)); } }
public FactMemento Load(string domain, FactID factId) { lock (this) { FactRecord factRecord = _factTable.FirstOrDefault(o => o.IdentifiedFactMemento.Id.Equals(factId)); if (factRecord != null) return factRecord.IdentifiedFactMemento.Memento; else throw new CorrespondenceException( string.Format("Fact with id {0} not found.", factId)); } }
public void CanSaveAndFindAFact() { Guid gameGuid = Guid.NewGuid(); var saveGame = NewGame(gameGuid); FactID saveId = _repository.Save(TestDomain, saveGame, TestClient); var findGame = NewGame(gameGuid); FactID?findId = _repository.FindExistingFact(TestDomain, findGame); Assert.IsNotNull(findId); Assert.AreEqual(saveId, findId); }
public FactMemento Load(string domain, FactID factId) { IdentifiedFactMemento identifiedMemento = null; using (var procedures = new Procedures(new Session(_connectionString))) { identifiedMemento = procedures.GetIdentifiedMemento(factId); } if (identifiedMemento == null) throw new CorrespondenceException(string.Format("Unable to find fact {0}", factId.key)); return identifiedMemento.Memento; }
public void SkipMessagesOriginatingFromThisClient() { Guid gameGuid = Guid.NewGuid(); var game = NewGame(gameGuid); FactID gameId = _repository.Save(TestDomain, game, TestClient); var saveMove = NewMove(gameId, 1); FactID saveId = _repository.Save(TestDomain, saveMove, TestClient); List <FactID> messages = _repository.LoadRecentMessages( TestDomain, gameId, TestClient, new TimestampID(0, 0)); Assert.AreEqual(0, messages.Count); }
public IdentifiedFactMemento GetIdentifiedMemento(FactID factId) { // Get the fact. _session.Command.CommandText = HEAD_SELECT + "WHERE f.FactID = @FactID " + TAIL_JOIN + "ORDER BY p.PredecessorID"; AddParameter("@FactID", factId.key); using (var loader = new Loader(_session.Command.ExecuteReader())) { _session.Command.Parameters.Clear(); return(loader.LoadMementos().FirstOrDefault()); } }
public void FactIsPublishedToPredecessor() { Guid gameGuid = Guid.NewGuid(); var game = NewGame(gameGuid); FactID gameId = _repository.Save(TestDomain, game, TestClient); var saveMove = NewMove(gameId, 1); FactID saveId = _repository.Save(TestDomain, saveMove, TestClient); List <FactID> messages = _repository.LoadRecentMessages( TestDomain, gameId, AnotherClient, new TimestampID(0, 0)); Assert.AreEqual(1, messages.Count); Assert.AreEqual(saveId, messages[0]); }
public FactMemento Load(string domain, FactID factId) { IdentifiedFactMemento identifiedMemento = null; using (var procedures = new Procedures(new Session(_connectionString))) { identifiedMemento = procedures.GetIdentifiedMemento(factId); } if (identifiedMemento == null) { throw new CorrespondenceException(string.Format("Unable to find fact {0}", factId.key)); } return(identifiedMemento.Memento); }
public void CanSaveAndFindAFactWithPredecessor() { Guid gameGuid = Guid.NewGuid(); var game = NewGame(gameGuid); FactID gameId = _repository.Save(TestDomain, game, TestClient); var saveMove = NewMove(gameId, 1); FactID saveId = _repository.Save(TestDomain, saveMove, TestClient); var findMove = NewMove(gameId, 1); FactID?findId = _repository.FindExistingFact(TestDomain, findMove); Assert.IsNotNull(findId); Assert.AreEqual(saveId, findId); }
private void Repository_PivotAffected(string domain, FactID pivotId, FactID factId, Guid clientGuid) { _messageBus.Notify(domain, pivotId); var subscribers = _repository.LoadWindowsPhoneSubscriptions(new List <FactID> { pivotId }, clientGuid); if (subscribers.Any()) { var messageBody = new FactTreeMemento(0); AddToFactTree(domain, messageBody, factId, null); SendWindowsPhonePushNotifications(subscribers, messageBody); } }
public void Notify(string domain, FactID pivotId) { List<Registration> registrations; lock (this) { registrations = _registrations .Where(n => n.Domain == domain && n.PivotId.Equals(pivotId)) .ToList(); } foreach (var registration in registrations) { registration.Notify(); } }
public FactMemento Load(string domain, FactID factId) { lock (this) { FactRecord factRecord = _factTable.FirstOrDefault(o => o.IdentifiedFactMemento.Id.Equals(factId)); if (factRecord != null) { return(factRecord.IdentifiedFactMemento.Memento); } else { throw new CorrespondenceException( string.Format("Fact with id {0} not found.", factId)); } } }
public void Notify(string domain, FactID pivotId) { List <Registration> registrations; lock (this) { registrations = _registrations .Where(n => n.Domain == domain && n.PivotId.Equals(pivotId)) .ToList(); } foreach (var registration in registrations) { registration.Notify(); } }
public void Notify(string domain, FactID pivotId) { List <Registration> registrations; lock (this) { Debug.WriteLine(String.Format("Notify all {0} of {1}", pivotId, _registrations.Count)); registrations = _registrations .Where(n => n.Domain == domain && n.PivotId.Equals(pivotId)) .ToList(); } foreach (var registration in registrations) { Debug.WriteLine(String.Format("Notify {0} {1}", registration.ClientGuid, registration.PivotId)); registration.Cancellation.Cancel(); } }
private bool FindExistingFact(FactMemento memento, out FactID id, Session session, bool readCommitted) { var existingFacts = FindExistingFacts(memento, session, readCommitted); if (existingFacts.Count > 1) { throw new CorrespondenceException(string.Format("More than one fact matched the given {0}.", memento.FactType)); } if (existingFacts.Count == 1) { id = existingFacts[0].Id; return(true); } else { id = new FactID(); return(false); } }
public List <FactID> GetRecentMessages(FactID pivotId, TimestampID timestamp, int clientId) { _session.Command.CommandText = "SELECT TOP (20) FactId " + "FROM Message " + "WHERE PivotId = @PivotId " + "AND FactId > @Timestamp " + "AND ClientId != @ClientId " + "ORDER BY FactId"; AddParameter("@PivotId", pivotId.key); AddParameter("@Timestamp", timestamp.Key); AddParameter("@ClientId", clientId); using (var loader = new Loader(_session.Command.ExecuteReader())) { _session.Command.Parameters.Clear(); return(loader.LoadIDs().ToList()); } }
public void CanUnpublishAFact() { Guid gameGuid = Guid.NewGuid(); var game = NewGame(gameGuid); FactID gameId = _repository.Save(TestDomain, game, TestClient); var move = NewMove(gameId, 1); FactID moveId = _repository.Save(TestDomain, move, TestClient); _repository.DeleteMessages(TestDomain, new List <UnpublishMemento> { new UnpublishMemento(moveId, MoveGame) }); List <FactID> messages = _repository.LoadRecentMessages( TestDomain, gameId, AnotherClient, new TimestampID(0, 0)); Assert.AreEqual(0, messages.Count); }
public void DontReturnSubscriptionsFromYourself() { Guid gameGuid = Guid.NewGuid(); var game = NewGame(gameGuid); FactID gameId = _repository.Save(TestDomain, game, TestClient); List <FactID> pivotIds = new List <FactID> { gameId }; _repository.SaveWindowsPhoneSubscription( pivotIds, "windows_phone_device_uri", TestClient); List <WindowsPhoneSubscription> subscriptions = _repository.LoadWindowsPhoneSubscriptions( pivotIds, TestClient); Assert.AreEqual(0, subscriptions.Count); }
public List <FactID> LoadRecentMessages(string domain, FactID pivotId, Guid clientGuid, TimestampID timestamp) { using (var session = new Session(_connectionString)) { int clientId = SaveClient(session, clientGuid); session.Command.CommandText = "SELECT TOP (20) FactId " + "FROM Message " + "WHERE PivotId = @PivotId " + "AND FactId > @Timestamp " + "AND ClientId != @ClientId " + "ORDER BY FactId"; AddParameter(session.Command, "@PivotId", pivotId.key); AddParameter(session.Command, "@Timestamp", timestamp.Key); AddParameter(session.Command, "@ClientId", clientId); using (IDataReader messageReader = session.Command.ExecuteReader()) { session.Command.Parameters.Clear(); return(LoadIDsFromReader(messageReader).ToList()); } } }
private bool FindExistingFact(FactMemento memento, out FactID id, Procedures procedures, bool readCommitted) { var existingFacts = FindExistingFacts(memento, procedures, readCommitted); if (existingFacts.Count > 1) throw new CorrespondenceException(string.Format( "More than one fact matched the given {0}.", memento.FactType)); if (existingFacts.Count == 1) { id = existingFacts[0].Id; return true; } else { id = new FactID(); return false; } }
private void Repository_PivotAffected(string domain, FactID pivotId) { _messageBus.Notify(domain, pivotId); }
public List<FactID> LoadRecentMessages(string domain, FactID pivotId, Guid clientGuid, TimestampID timestamp) { using (var procedures = new Procedures(new Session(_connectionString))) { int clientId = SaveClient(procedures, clientGuid); return procedures.GetRecentMessages(pivotId, timestamp, clientId); } }
public FactID Save(string domain, FactMemento fact, Guid clientGuid) { // Retry on concurrency failure. while (true) { using (var procedures = new Procedures(new Session(_connectionString))) { procedures.BeginTransaction(); // First see if the fact is already in storage. FactID id; if (FindExistingFact(fact, out id, procedures, readCommitted: true)) { return(id); } // It isn't there, so store it. int typeId = SaveType(procedures, fact.FactType); id = procedures.InsertFact(fact, typeId); // Store the predecessors. foreach (PredecessorMemento predecessor in fact.Predecessors) { int roleId = SaveRole(procedures, predecessor.Role); procedures.InsertPredecessor(id, predecessor, roleId); } // Store a message for each pivot. FactID newFactId = id; List <AncestorMessage> pivotMessages = fact.Predecessors .Where(predecessor => predecessor.IsPivot) .Select(predecessor => new AncestorMessage { AncestorFactId = newFactId, AncestorRoleId = SaveRole(procedures, predecessor.Role), Message = new MessageMemento(predecessor.ID, newFactId) }) .ToList(); // Store messages for each non-pivot. This fact belongs to all predecessors' pivots. string[] nonPivots = fact.Predecessors .Where(predecessor => !predecessor.IsPivot) .Select(predecessor => predecessor.ID.key.ToString()) .ToArray(); List <AncestorMessage> nonPivotMessages; if (nonPivots.Length > 0) { var predecessorsPivotRoles = procedures.GetAncestorPivots(nonPivots); nonPivotMessages = predecessorsPivotRoles .Select(predecessorPivot => new AncestorMessage { AncestorFactId = predecessorPivot.AncestorFactId, AncestorRoleId = predecessorPivot.AncestorRoleId, Message = new MessageMemento(predecessorPivot.PivotId, newFactId) }) .ToList(); } else { nonPivotMessages = new List <AncestorMessage>(); } int clientId = SaveClient(procedures, clientGuid); var roleMessages = pivotMessages.Union(nonPivotMessages).Distinct().ToList(); procedures.InsertMessages(roleMessages, clientId); // Optimistic concurrency check. // Make sure we don't find more than one. var existingFacts = FindExistingFacts(fact, procedures, readCommitted: false); if (existingFacts.Count == 1) { procedures.Commit(); if (roleMessages.Any() && PivotAffected != null) { foreach (var roleMessage in roleMessages) { PivotAffected(domain, roleMessage.Message.PivotId, roleMessage.Message.FactId, clientGuid); } } return(id); } else { _retried = true; } } } }
private void Unpublish(FactID factId, RoleMemento role) { _messageTable.RemoveAll(message => message.AncestorFact.Equals(factId) && message.AncestorRole.Equals(role)); }
public FactID Save(string domain, FactMemento fact, Guid clientGuid) { FactID factId; List <FactID> affectedPivots; lock (this) { // See if the fact already exists. FactRecord existingFact = _factTable.FirstOrDefault(o => o.IdentifiedFactMemento.Memento.Equals(fact)); if (existingFact == null) { // It doesn't, so create it. FactID newFactID = new FactID() { key = _factTable.Count + 1 }; factId = newFactID; existingFact = new FactRecord() { IdentifiedFactMemento = new IdentifiedFactMemento(factId, fact) }; _factTable.Add(existingFact); // Store a message for each pivot. var pivots = fact.Predecessors .Where(predecessor => predecessor.IsPivot); _messageTable.AddRange(pivots .Select(predecessor => new MessageRecord( new MessageMemento(predecessor.ID, newFactID), newFactID, predecessor.Role, clientGuid))); // Store messages for each non-pivot. This fact belongs to all predecessors' pivots. List <FactID> nonPivots = fact.Predecessors .Where(predecessor => !predecessor.IsPivot) .Select(predecessor => predecessor.ID) .ToList(); List <MessageRecord> predecessorsPivots = _messageTable .Where(message => nonPivots.Contains(message.Message.FactId)) .Distinct() .ToList(); _messageTable.AddRange(predecessorsPivots .Select(predecessorPivot => new MessageRecord( new MessageMemento(predecessorPivot.Message.PivotId, newFactID), predecessorPivot.AncestorFact, predecessorPivot.AncestorRole, clientGuid))); affectedPivots = pivots .Select(pivot => pivot.ID) .Union(predecessorsPivots .Select(predecessorPivot => predecessorPivot.Message.PivotId)) .ToList(); } else { factId = existingFact.IdentifiedFactMemento.Id; affectedPivots = null; } } if (affectedPivots != null && affectedPivots.Any() && PivotAffected != null) { foreach (var pivotId in affectedPivots) { PivotAffected(domain, pivotId, factId, clientGuid); } } return(factId); }
public List <FactID> LoadRecentMessages(string domain, FactID localPivotId, Guid clientGuid, TimestampID timestamp) { return(_messageTable.Where(message => message.Message.PivotId.Equals(localPivotId) && message.Message.FactId.key > timestamp.Key && message.Source != clientGuid).Select(message => message.Message.FactId).Distinct() .ToList()); }
private void Repository_PivotAffected(string domain, FactID pivotId, FactID factId, Guid clientGuid) { _messageBus.Notify(domain, pivotId); var subscribers = _repository.LoadWindowsPhoneSubscriptions(new List<FactID> { pivotId }, clientGuid); if (subscribers.Any()) { var messageBody = new FactTreeMemento(0); AddToFactTree(domain, messageBody, factId, null); SendWindowsPhonePushNotifications(subscribers, messageBody); } }
private void AddToFactTree(string domain, FactTreeMemento messageBody, FactID factId, Dictionary<FactID, FactID> localIdByRemoteId) { if (!messageBody.Contains(factId)) { FactMemento fact = _repository.Load(domain, factId); foreach (PredecessorMemento predecessor in fact.Predecessors) AddToFactTree(domain, messageBody, predecessor.ID, localIdByRemoteId); messageBody.Add(new IdentifiedFactMemento(factId, fact)); } }
public IdentifiedFactMemento GetIdentifiedMemento(FactID factId) { // Get the fact. _session.Command.CommandText = HEAD_SELECT + "WHERE f.FactID = @FactID " + TAIL_JOIN + "ORDER BY p.PredecessorID"; AddParameter("@FactID", factId.key); using (var loader = new Loader(_session.Command.ExecuteReader())) { _session.Command.Parameters.Clear(); return loader.LoadMementos().FirstOrDefault(); } }
public FactID Save(string domain, FactMemento fact, Guid clientGuid) { // Retry on concurrency failure. while (true) { using (var session = new Session(_connectionString)) { session.BeginTransaction(); // First see if the fact is already in storage. FactID id; if (FindExistingFact(fact, out id, session, readCommitted: true)) { return(id); } // It isn't there, so store it. int typeId = SaveType(session, fact.FactType); session.Command.CommandText = "INSERT Fact (FKTypeID, Data, Hashcode) VALUES (@TypeID, @Data, @Hashcode)"; AddParameter(session.Command, "@TypeID", typeId); AddParameter(session.Command, "@Data", fact.Data); AddParameter(session.Command, "@Hashcode", fact.GetHashCode()); session.Command.ExecuteNonQuery(); session.Command.Parameters.Clear(); session.Command.CommandText = "SELECT @@IDENTITY"; decimal result = (decimal)session.Command.ExecuteScalar(); session.Command.Parameters.Clear(); id.key = (Int64)result; // Store the predecessors. foreach (PredecessorMemento predecessor in fact.Predecessors) { int roleId = SaveRole(session, predecessor.Role); session.Command.CommandText = "INSERT Predecessor (FKFactID, FKRoleID, FKPredecessorFactID, IsPivot) VALUES (@FactID, @RoleID, @PredecessorFactID, @IsPivot)"; AddParameter(session.Command, "@FactID", id.key); AddParameter(session.Command, "@RoleID", roleId); AddParameter(session.Command, "@PredecessorFactID", predecessor.ID.key); AddParameter(session.Command, "@IsPivot", predecessor.IsPivot); session.Command.ExecuteNonQuery(); session.Command.Parameters.Clear(); } // Store a message for each pivot. FactID newFactId = id; List <MessageMemento> pivotMessages = fact.Predecessors .Where(predecessor => predecessor.IsPivot) .Select(predecessor => new MessageMemento(predecessor.ID, newFactId)) .ToList(); // Store messages for each non-pivot. This fact belongs to all predecessors' pivots. string[] nonPivots = fact.Predecessors .Where(predecessor => !predecessor.IsPivot) .Select(predecessor => predecessor.ID.key.ToString()) .ToArray(); List <MessageMemento> nonPivotMessages; if (nonPivots.Length > 0) { string nonPivotGroup = string.Join(",", nonPivots); session.Command.CommandText = string.Format( "SELECT DISTINCT PivotId FROM Message WHERE FactId IN ({0})", nonPivotGroup); List <FactID> predecessorsPivots; using (IDataReader predecessorPivotReader = session.Command.ExecuteReader()) { session.Command.Parameters.Clear(); predecessorsPivots = LoadIDsFromReader(predecessorPivotReader).ToList(); } nonPivotMessages = predecessorsPivots .Select(predecessorPivot => new MessageMemento(predecessorPivot, newFactId)) .ToList(); } else { nonPivotMessages = new List <MessageMemento>(); } int clientId = SaveClient(session, clientGuid); var messages = pivotMessages.Union(nonPivotMessages).Distinct().ToList(); SaveMessages(session, messages, clientId); // Optimistic concurrency check. // Make sure we don't find more than one. var existingFacts = FindExistingFacts(fact, session, readCommitted: false); if (existingFacts.Count == 1) { session.Commit(); if (messages.Any() && PivotAffected != null) { foreach (var message in messages) { PivotAffected(domain, message.PivotId); } } return(id); } else { _retried = true; } } } }
private static FactMemento NewMove(FactID gameId, byte moveIndex) { var move = new FactMemento(MoveType); move.Data = new byte[] { moveIndex }; move.AddPredecessor(MoveGame, gameId, true); return move; }
public List<FactID> GetRecentMessages(FactID pivotId, TimestampID timestamp, int clientId) { _session.Command.CommandText = "SELECT TOP (20) FactId " + "FROM Message " + "WHERE PivotId = @PivotId " + "AND FactId > @Timestamp " + "AND ClientId != @ClientId " + "ORDER BY FactId"; AddParameter("@PivotId", pivotId.key); AddParameter("@Timestamp", timestamp.Key); AddParameter("@ClientId", clientId); using (var loader = new Loader(_session.Command.ExecuteReader())) { _session.Command.Parameters.Clear(); return loader.LoadIDs().ToList(); } }
public FactID Save(string domain, FactMemento fact, Guid clientGuid) { FactID factId; List<FactID> affectedPivots; lock (this) { // See if the fact already exists. FactRecord existingFact = _factTable.FirstOrDefault(o => o.IdentifiedFactMemento.Memento.Equals(fact)); if (existingFact == null) { // It doesn't, so create it. FactID newFactID = new FactID() { key = _factTable.Count + 1 }; factId = newFactID; existingFact = new FactRecord() { IdentifiedFactMemento = new IdentifiedFactMemento(factId, fact) }; _factTable.Add(existingFact); // Store a message for each pivot. var pivots = fact.Predecessors .Where(predecessor => predecessor.IsPivot); _messageTable.AddRange(pivots .Select(predecessor => new MessageRecord( new MessageMemento(predecessor.ID, newFactID), newFactID, predecessor.Role, clientGuid))); // Store messages for each non-pivot. This fact belongs to all predecessors' pivots. List<FactID> nonPivots = fact.Predecessors .Where(predecessor => !predecessor.IsPivot) .Select(predecessor => predecessor.ID) .ToList(); List<MessageRecord> predecessorsPivots = _messageTable .Where(message => nonPivots.Contains(message.Message.FactId)) .Distinct() .ToList(); _messageTable.AddRange(predecessorsPivots .Select(predecessorPivot => new MessageRecord( new MessageMemento(predecessorPivot.Message.PivotId, newFactID), predecessorPivot.AncestorFact, predecessorPivot.AncestorRole, clientGuid))); affectedPivots = pivots .Select(pivot => pivot.ID) .Union(predecessorsPivots .Select(predecessorPivot => predecessorPivot.Message.PivotId)) .ToList(); } else { factId = existingFact.IdentifiedFactMemento.Id; affectedPivots = null; } } if (affectedPivots != null && affectedPivots.Any() && PivotAffected != null) foreach (var pivotId in affectedPivots) PivotAffected(domain, pivotId, factId, clientGuid); return factId; }
public List<FactID> LoadRecentMessages(string domain, FactID localPivotId, Guid clientGuid, TimestampID timestamp) { return _messageTable.Where(message => message.Message.PivotId.Equals(localPivotId) && message.Message.FactId.key > timestamp.Key && message.Source != clientGuid).Select(message => message.Message.FactId).Distinct() .ToList(); }