Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
    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);
    }
Esempio n. 6
0
    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);
    }
Esempio n. 7
0
        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();
            }
        }