Skip to content
quarry Artifact [3b79aa9e3d]
Login

Artifact [3b79aa9e3d]

Artifact 3b79aa9e3d6762e3bcce28f09482f41bd0f9f454022b26d729483e0d879e9315:


// mention.go records that a handle was mentioned, before the trigger
// is raised (RFC 0011 §4). The row is the operational fact
// `chat.mentioned` is backed by — a mention that was never recorded is
// a mention notify was never told about, so this write happens on the
// path that decides to notify, not as an afterthought.
package oltp

const mentionSchema = `
CREATE TABLE IF NOT EXISTS mention (
	repo TEXT NOT NULL,
	ref  TEXT NOT NULL, -- "chat:<seq>" | "forum:<hash>"
	who  TEXT NOT NULL,
	by   TEXT NOT NULL,
	at   TEXT NOT NULL,
	PRIMARY KEY (repo, ref, who)
);`

// RecordMention records one mention, idempotently: the same (repo,
// ref, who) replayed is a no-op, exactly as the address-based
// idempotency keys in RFC 0011 §4 intend — a retried or re-ingested
// trigger must never appear as a second row.
func (d *DB) RecordMention(repo, ref, who, by string) error {
	if repo == "" || ref == "" || who == "" {
		return nil
	}
	_, err := d.w.Exec(`INSERT OR IGNORE INTO mention (repo, ref, who, by, at)
		VALUES (?, ?, ?, ?, ?)`, repo, ref, who, by, now())
	return err
}

// Mentions returns who was mentioned at ref, for tests and for any
// future reader that needs the raw rows rather than a notify trigger.
func (d *DB) Mentions(repo, ref string) ([]string, error) {
	rows, err := d.db.Query(`SELECT who FROM mention WHERE repo = ? AND ref = ? ORDER BY who`, repo, ref)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var out []string
	for rows.Next() {
		var who string
		if err := rows.Scan(&who); err != nil {
			return nil, err
		}
		out = append(out, who)
	}
	return out, rows.Err()
}