Sobes.tech
Senior

Exercice de conception : il existe un système pour des groupes de réponse rapide. Lorsqu'un signal est reçu, trois groupes répondent simultanément. Il faut n'envoyer qu'un seul groupe. Comment faire cela au niveau des transactions dans la base de données ?

sobes.tech IA

Réponse de l'IA

Для решения задачи с одновременным откликом нескольких групп и выбором только одной на уровне транзакций в базе данных можно использовать механизм блокировок и уникальных ограничений.

Подход:

  1. Создайте таблицу, например, signal_assignments, где хранится информация о том, какая группа назначена на сигнал.
  2. При получении сигнала каждая группа пытается вставить запись с уникальным ключом по сигналу (например, signal_id с уникальным индексом).
  3. Первая транзакция, которая успешно вставит запись, «захватывает» сигнал.
  4. Остальные транзакции при попытке вставки получат ошибку уникального ограничения и должны откатиться или повторить попытку.

Пример на SQL:

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

При обработке сигнала в транзакции:

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

Если вставка не удалась из-за уже существующей записи, значит сигнал уже назначен другой группе.

В Go с использованием транзакций:

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 {
        // Ошибка уникального ограничения — сигнал уже назначен
        return err
    }

    return tx.Commit()
}

Таким образом, на уровне базы данных гарантируется, что только одна группа будет назначена на сигнал, несмотря на одновременные попытки.