private void ClearDeviceMessages(Transaction transaction) { var deviceMsgs = transaction.edus.Where(m => m.edu_type == "m.direct_to_device").ToList() .ConvertAll(m => m.StreamId); var deviceLists = transaction.edus.Where(m => m.edu_type == "m.device_list_update").ToList() .ConvertAll(m => Tuple.Create(m.StreamId, (string)m.content["user_id"])); using (var db = new SynapseDbContext(_connString)) { if (deviceMsgs.Count != 0) { _destLastDeviceMsgStreamId[transaction.destination] = deviceMsgs.Max(); var deviceMsgEntries = db.DeviceFederationOutboxes.Where(m => deviceMsgs.Contains(m.StreamId)); if (deviceMsgEntries.Any()) { db.DeviceFederationOutboxes.RemoveRange(deviceMsgEntries); db.SaveChanges(); } else { log.Warning("No messages to delete in outbox, despite sending messages in this txn"); } } if (deviceLists.Count == 0) { return; } _destLastDeviceListStreamId[transaction.destination] = deviceLists.Max(e => e.Item1); var deviceListEntries = db.DeviceListsOutboundPokes .Where(m => deviceLists.FindIndex(e => e.Item1 == m.StreamId && e.Item2 == m.UserId) >= 0); if (deviceListEntries.Any()) { foreach (var msg in deviceListEntries) { msg.Sent = true; } db.SaveChanges(); } else { log.Warning("No device lists to mark as sent, despite sending lists in this txn"); } } }
private void UpdateFederationPos(string type, int id) { using (var db = new SynapseDbContext(connectionString)) { var res = db.FederationStreamPosition.SingleOrDefault(r => r.Type == type); if (res != null) { res.StreamId = id; db.SaveChanges(); } } }
private async Task ProcessPendingEvents() { List <EventJsonSet> events; var top = _lastEventPoke; int last; // Get the set of events we need to process. using (var db = new SynapseDbContext(_connString)) { last = (await db.FederationStreamPosition.SingleAsync(m => m.Type == "events")).StreamId; events = db.GetAllNewEventsStream(last, top, MAX_PDUS_PER_TRANSACTION); } if (events.Count == 0) { log.Debug("No new events to handle"); return; } if (events.Count == MAX_PDUS_PER_TRANSACTION) { log.Warning("More than {Max} events behind", MAX_PDUS_PER_TRANSACTION); top = events.Last().StreamOrdering; } log.Information("Processing from {last} to {top}", last, top); // Skip any events that didn't come from us. foreach (var item in events.Where(e => IsMineId(e.Sender)).GroupBy(e => e.RoomId)) { var hosts = await GetHostsInRoom(item.Key); foreach (var roomEvent in item) { // TODO: Support send_on_bahalf_of? IPduEvent pduEv; // NOTE: This is an event format version, not room version. if (roomEvent.Version == 1) { pduEv = new PduEventV1 { event_id = roomEvent.EventId } } ; else // Default to latest event format version. { pduEv = new PduEventV2(); } pduEv.content = roomEvent.Content["content"] as JObject; pduEv.origin = _serverName; pduEv.depth = (long)roomEvent.Content["depth"]; pduEv.auth_events = roomEvent.Content["auth_events"]; pduEv.prev_events = roomEvent.Content["prev_events"]; pduEv.origin_server_ts = (long)roomEvent.Content["origin_server_ts"]; if (roomEvent.Content.ContainsKey("redacts")) { pduEv.redacts = (string)roomEvent.Content["redacts"]; } pduEv.room_id = roomEvent.RoomId; pduEv.sender = roomEvent.Sender; pduEv.prev_state = roomEvent.Content["prev_state"]; if (roomEvent.Content.ContainsKey("state_key")) { pduEv.state_key = (string)roomEvent.Content["state_key"]; } pduEv.type = (string)roomEvent.Content["type"]; pduEv.unsigned = (JObject)roomEvent.Content["unsigned"]; pduEv.hashes = roomEvent.Content["hashes"]; pduEv.signatures = new Dictionary <string, Dictionary <string, string> >(); foreach (var sigHosts in (JObject)roomEvent.Content["signatures"]) { pduEv.signatures.Add(sigHosts.Key, new Dictionary <string, string>()); foreach (var sigs in (JObject)sigHosts.Value) { pduEv.signatures[sigHosts.Key].Add(sigs.Key, sigs.Value.Value <string>()); } } //TODO: I guess we need to fetch the destinations for each event in a room, because someone may have got banned in between. foreach (var host in hosts) { var transaction = GetOrCreateTransactionForDest(host); transaction.pdus.Add(pduEv); AttemptTransaction(host); } } } using (var db = new SynapseDbContext(_connString)) { log.Debug("Saving position {top} to DB", top); var streamPos = db.FederationStreamPosition.First(e => e.Type == "events"); streamPos.StreamId = top; db.SaveChanges(); } // Still behind? if (events.Count == MAX_PDUS_PER_TRANSACTION) { log.Information("Calling ProcessPendingEvents again because we are still behind"); await ProcessPendingEvents(); } }