public async Task AddSwitch(IPKConnection conn, SystemId system, IReadOnlyCollection <MemberId> members) { // Use a transaction here since we're doing multiple executed commands in one await using var tx = await conn.BeginTransactionAsync(); // First, we insert the switch itself var sw = await conn.QuerySingleAsync <PKSwitch>("insert into switches(system) values (@System) returning *", new { System = system }); // Then we insert each member in the switch in the switch_members table await using (var w = conn.BeginBinaryImport("copy switch_members (switch, member) from stdin (format binary)")) { foreach (var member in members) { await w.StartRowAsync(); await w.WriteAsync(sw.Id.Value, NpgsqlDbType.Integer); await w.WriteAsync(member.Value, NpgsqlDbType.Integer); } await w.CompleteAsync(); } // Finally we commit the tx, since the using block will otherwise rollback it await tx.CommitAsync(); _logger.Information("Created {SwitchId} in {SystemId}: {Members}", sw.Id, system, members); }
public static async Task AddMembersToGroup(this IPKConnection conn, GroupId group, IEnumerable <MemberId> members) { await using var w = conn.BeginBinaryImport("copy group_members (group_id, member_id) from stdin (format binary)"); foreach (var member in members) { await w.StartRowAsync(); await w.WriteAsync(group.Value); await w.WriteAsync(member.Value); } await w.CompleteAsync(); }
public async Task AddGroupsToMember(IPKConnection conn, MemberId member, IReadOnlyCollection <GroupId> groups) { await using var w = conn.BeginBinaryImport("copy group_members (group_id, member_id) from stdin (format binary)"); foreach (var group in groups) { await w.StartRowAsync(); await w.WriteAsync(group.Value); await w.WriteAsync(member.Value); } await w.CompleteAsync(); _logger.Information("Added member {MemberId} to groups {GroupIds}", member, groups); }
public async Task AddMembersToGroup(IPKConnection conn, GroupId group, IReadOnlyCollection <MemberId> members) { await using var w = conn.BeginBinaryImport("copy group_members (group_id, member_id) from stdin (format binary)"); foreach (var member in members) { await w.StartRowAsync(); await w.WriteAsync(group.Value); await w.WriteAsync(member.Value); } await w.CompleteAsync(); _logger.Information("Added members to {GroupId}: {MemberIds}", group, members); }
public async Task <PKSwitch> AddSwitch(IPKConnection conn, SystemId system, IReadOnlyCollection <MemberId> members) { // Use a transaction here since we're doing multiple executed commands in one await using var tx = await conn.BeginTransactionAsync(); // First, we insert the switch itself var sw = await conn.QuerySingleAsync <PKSwitch>("insert into switches(system) values (@System) returning *", new { System = system }); // Then we insert each member in the switch in the switch_members table await using (var w = conn.BeginBinaryImport("copy switch_members (switch, member) from stdin (format binary)")) { foreach (var member in members) { await w.StartRowAsync(); await w.WriteAsync(sw.Id.Value, NpgsqlDbType.Integer); await w.WriteAsync(member.Value, NpgsqlDbType.Integer); } await w.CompleteAsync(); } // Finally we commit the tx, since the using block will otherwise rollback it await tx.CommitAsync(); _logger.Information("Created {SwitchId} in {SystemId}: {Members}", sw.Id, system, members); _ = _dispatch.Dispatch(sw.Id, new UpdateDispatchData { Event = DispatchEvent.CREATE_SWITCH, EventData = JObject.FromObject(new { id = sw.Uuid.ToString(), timestamp = sw.Timestamp.FormatExport(), members = await GetMemberGuids(members), }), }); return(sw); }
public async Task EditSwitch(IPKConnection conn, SwitchId switchId, IReadOnlyCollection <MemberId> members) { // Use a transaction here since we're doing multiple executed commands in one await using var tx = await conn.BeginTransactionAsync(); // Remove the old members from the switch await conn.ExecuteAsync("delete from switch_members where switch = @Switch", new { Switch = switchId }); // Add the new members await using (var w = conn.BeginBinaryImport("copy switch_members (switch, member) from stdin (format binary)")) { foreach (var member in members) { await w.StartRowAsync(); await w.WriteAsync(switchId.Value, NpgsqlDbType.Integer); await w.WriteAsync(member.Value, NpgsqlDbType.Integer); } await w.CompleteAsync(); } // Finally we commit the tx, since the using block will otherwise rollback it await tx.CommitAsync(); _ = _dispatch.Dispatch(switchId, new UpdateDispatchData { Event = DispatchEvent.UPDATE_SWITCH, EventData = JObject.FromObject(new { members = await GetMemberGuids(members), }), }); _logger.Information("Updated {SwitchId} members: {Members}", switchId, members); }
public async Task AddSwitches(IReadOnlyCollection <SwitchInfo> switches) { // Ensure we're aware of all the members we're trying to import from if (!switches.All(sw => sw.MemberIdentifiers.All(m => _knownMembers.ContainsKey(m)))) { throw new ArgumentException("One or more switch members haven't been added using this importer"); } // Fetch the existing switches in the database so we can avoid duplicates var existingSwitches = (await _conn.QueryAsync <PKSwitch>("select * from switches where system = @System", new { System = _systemId })).ToList(); var existingTimestamps = existingSwitches.Select(sw => sw.Timestamp).ToImmutableHashSet(); var lastSwitchId = existingSwitches.Count != 0 ? existingSwitches.Select(sw => sw.Id).Max() : (SwitchId?)null; // Import switch definitions var importedSwitches = new Dictionary <Instant, SwitchInfo>(); await using (var importer = _conn.BeginBinaryImport("copy switches (system, timestamp) from stdin (format binary)")) { foreach (var sw in switches) { // Don't import duplicate switches if (existingTimestamps.Contains(sw.Timestamp)) { continue; } // Otherwise, write to importer await importer.StartRowAsync(); await importer.WriteAsync(_systemId.Value, NpgsqlDbType.Integer); await importer.WriteAsync(sw.Timestamp, NpgsqlDbType.Timestamp); // Note that we've imported a switch with this timestamp importedSwitches[sw.Timestamp] = sw; } // Commit the import await importer.CompleteAsync(); } // Now, fetch all the switches we just added (so, now we get their IDs too) // IDs are sequential, so any ID in this system, with a switch ID > the last max, will be one we just added var justAddedSwitches = await _conn.QueryAsync <PKSwitch>( "select * from switches where system = @System and id > @LastSwitchId", new { System = _systemId, LastSwitchId = lastSwitchId?.Value ?? -1 }); // Lastly, import the switch members await using (var importer = _conn.BeginBinaryImport("copy switch_members (switch, member) from stdin (format binary)")) { foreach (var justAddedSwitch in justAddedSwitches) { if (!importedSwitches.TryGetValue(justAddedSwitch.Timestamp, out var switchInfo)) { throw new Exception($"Found 'just-added' switch (by ID) with timestamp {justAddedSwitch.Timestamp}, but this did not correspond to a timestamp we just added a switch entry of! :/"); } // We still assume timestamps are unique and non-duplicate, so: var members = switchInfo.MemberIdentifiers; foreach (var memberIdentifier in members) { if (!_knownMembers.TryGetValue(memberIdentifier, out var memberId)) { throw new Exception($"Attempted to import switch with member identifier {memberIdentifier} but could not find an entry in the id map for this! :/"); } await importer.StartRowAsync(); await importer.WriteAsync(justAddedSwitch.Id.Value, NpgsqlDbType.Integer); await importer.WriteAsync(memberId.Value, NpgsqlDbType.Integer); } } await importer.CompleteAsync(); } }