fix(11-08): document foreign and nested transaction refusal

- lagoon.Transaction doc and README state that a nested call over a root
  handle returns an error instead of opening an independent transaction
- beachcomber README no longer promises an immediate sync inside a plain
  GORM transaction; it is warned and skipped since 11-08
This commit is contained in:
Jakub Zych
2026-09-30 21:00:20 +02:00
parent 2766f34d99
commit 8e0083ed41
3 changed files with 5 additions and 2 deletions

View File

@@ -31,7 +31,7 @@ The package itself knows no search server. An engine package registers itself fr
## Sync semantics
- **After commit.** The callbacks register the sync with `lagoon.AfterCommit`. Inside `lagoon.Transaction` it runs after that transaction commits, and not at all when it rolls back. A single-statement write, for which GORM opens its own transaction, syncs after that commit and not when the write fails. Inside a plain `gorm` transaction there is no commit hook, so the sync runs immediately through the transaction's handle. Its reads run in a savepoint, so a failed read never aborts the caller's transaction, including a read that the application Gate swallows and counts as off.
- **After commit.** The callbacks register the sync with `lagoon.AfterCommit`. Inside `lagoon.Transaction` it runs after that transaction commits, and not at all when it rolls back. A single-statement write, for which GORM opens its own transaction, syncs after that commit and not when the write fails. Inside a plain `gorm` transaction Lagoon cannot observe the commit, so `lagoon.AfterCommit` logs a warning and the sync is skipped; wrap such writes in `lagoon.Transaction`, or call `Sync` after the commit. The sync's reads run in a savepoint, so when `Sync` or `Remove` is handed a transaction a failed read never aborts it, including a read that the application Gate swallows and counts as off.
- **Inline and non-fatal.** The sync runs in the writing goroutine, after the commit, so a create followed by a search sees the document. Every engine request is bounded by the engine's timeout (`search.typesense.connection_timeout_seconds`), and the caller's context cancellation does not abandon it. A failure, a timeout or a panic is logged at Warn as `search: sync failed` with the index, key and operation. The write is already committed and stays so. The log never carries the document or the API key.
- **Three gates, before any request.** Nothing is sent when:
1. the engine is not configured (the `null` engine, or Typesense with an empty `search.typesense.api_key`);