Sobes.tech
Senior

Design task: there is a system for rapid response teams. A signal comes in, and three teams respond to it simultaneously. Only one team needs to be sent. How can this be done at the database transaction level?

sobes.tech AI

Answer from AI

To solve the problem of simultaneous responses from multiple groups with only one being selected at the transaction level in the database, you can use locking mechanisms and unique constraints.

Approach:

  1. Create a table, for example, signal_assignments, where information about which group is assigned to a signal is stored.
  2. When a signal is received, each group attempts to insert a record with a unique key on the signal (for example, signal_id with a unique index).
  3. The first transaction that successfully inserts the record 'captures' the signal.
  4. Other transactions attempting to insert will encounter a unique constraint error and should rollback or retry.

SQL example:

CREATE TABLE signal_assignments (
    signal_id UUID PRIMARY KEY,
    group_id UUID NOT NULL
);

When processing the signal in a transaction:

BEGIN;
INSERT INTO signal_assignments(signal_id, group_id) VALUES (:signal_id, :group_id);
COMMIT;

If the insert fails due to an existing record, it means the signal has already been assigned to another group.

In Go using transactions:

func assignGroup(db *sql.DB, signalID, groupID string) error {
    tx, err := db.Begin()
    if err != nil {
        return err
    }
    defer tx.Rollback()

    _, err = tx.Exec(`INSERT INTO signal_assignments(signal_id, group_id) VALUES ($1, $2)`, signalID, groupID)
    if err != nil {
        // Unique constraint error — signal already assigned
        return err
    }

    return tx.Commit()
}

Thus, at the database level, it is guaranteed that only one group will be assigned to a signal, despite concurrent attempts.

Design task: there is a system for rapid response… - sobes.tech