private static void Stream_DataRow(object sender, EventStreamRow e) { if (e.Kind != EventStreamRow.RowKind.Event) { return; // We don't parse state events } if (!EmojiEventParser.CanParse(e.EventType)) { return; } EventJson ev; using (var db = new SynapseDbContext(_config.GetConnectionString("synapse"))) { ev = db.EventsJson.FirstOrDefault(e2 => e2.RoomId == e.RoomId && e2.EventId == e.EventId); if (ev == null) { return; } } var emoji = EmojiEventParser.CountEmoji(e.EventType, ev).Where(c => c.Value > 0); foreach (var pair in emoji) { log.Information("Found {0} instances of {1} emoji in type {2}", pair.Value, pair.Key, e.EventType); _redis.GetSubscriber().PublishAsync(EmojiChannel.IncrementCommands, IncrementCommand.Make(pair.Key, pair.Value, e.EventType)); _redisDb.StringIncrementAsync(pair.Key, pair.Value, CommandFlags.FireAndForget); } }
private async Task <int> GetFederationPos(string type) { using (var db = new SynapseDbContext(connectionString)) { var query = db.FederationStreamPosition.Where(r => r.Type == type); var res = await query.FirstOrDefaultAsync(); return(res?.StreamId ?? -1); } }
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 <HashSet <string> > GetHostsInRoom(string roomId) { var hosts = new HashSet <string>(); using (var db = new SynapseDbContext(_connString)) { await db.RoomMemberships.Where(m => m.RoomId == roomId) .ForEachAsync(m => hosts.Add(m.UserId.Split(":")[1])); } hosts.Remove(_serverName); return(hosts); }
private static void Stream_DataRow(object sender, EventStreamRow e) { using (var db = new SynapseDbContext(_config.GetConnectionString("synapse"))) { log.Information("Received event {0} ({1}) in {2}", e.EventId, e.EventType, e.RoomId); var ev = db.EventsJson.SingleOrDefault(e2 => e2.RoomId == e.RoomId && e2.EventId == e.EventId); if (ev != null) { log.Information(ev.Json); } else { log.Error("EVENT NOT FOUND"); } } }
private Tuple <List <DeviceFederationOutbox>, List <DeviceContentSet> > GetNewDeviceMessages(string destination) { var lastMsgId = _destLastDeviceMsgStreamId.GetValueOrDefault(destination, 0); var lastListId = _destLastDeviceListStreamId.GetValueOrDefault(destination, 0); using (var db = new SynapseDbContext(_connString)) { var messages = db .DeviceFederationOutboxes .Where(message => message.Destination == destination && message.StreamId > lastMsgId) .OrderBy(message => message.StreamId).Take(MAX_EDUS_PER_TRANSACTION).ToList(); var resLists = db.GetNewDevicesForDestination(destination, MAX_EDUS_PER_TRANSACTION); return(Tuple.Create(messages, resLists)); } }
/// <summary> /// Get a set of remote hosts interested in this presence. /// </summary> private async Task <Dictionary <string[], PresenceState> > GetInterestedRemotes(List <PresenceState> presenceSet) { var dict = new Dictionary <string[], PresenceState>(); using (var db = new SynapseDbContext(_connString)) { // Get the list of rooms shared by these users. // We are intentionally skipping presence lists here. foreach (var presence in presenceSet) { var membershipList = await db .RoomMemberships .Where(m => m.Membership == "join" && m.UserId == presence.user_id).ToListAsync(); var hosts = new HashSet <string>(); // XXX: This is NOT the way to do this, but functions well enough // for a demo. foreach (var roomId in membershipList.ConvertAll(m => m.RoomId)) { await db.RoomMemberships .Where(m => m.RoomId == roomId) .ForEachAsync(m => hosts.Add(m.UserId .Split(":") [1])); } // Never include ourselves hosts.Remove(_serverName); // Now get the hosts for that room. dict.Add(hosts.ToArray(), presence); } } return(dict); }
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(); } }