Sobes.tech
Senior

Жобалоо тапшырмасы: тез жооп берүүчү топтор үчүн система бар. Белгилүү бир сигнал келгенде, үч топ бир убакта жооп берет. Бир гана топту жөнөтүү керек. Бул ишти маалыматтар базасындагы транзакциялар деңгээлинде кантип жасаса болот?

sobes.tech AI

AIден жооп

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

Подход:

  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()
}

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