Rules Hub
Code Ruleset
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Re-read shared state after a create-if-missing attempt
When resolving initially missing records after an idempotent creation attempt, read the resulting shared state even if this caller inserted zero rows. Another concurrent writer may have created the records.
Bad example
| 1 | type Catalog = { |
| 2 | find(ids: string[]): Promise<string[]>; |
| 3 | ensure(ids: string[]): Promise<number>; |
| 4 | }; |
| 5 |
|
| 6 | async function resolve(ids: string[], catalog: Catalog) { |
| 7 | let found = await catalog.find(ids); |
| 8 | const missing = ids.filter(id => !found.includes(id)); |
| 9 | if (missing.length > 0 && await catalog.ensure(missing) > 0) { |
| 10 | found = await catalog.find(ids); |
| 11 | } |
| 12 | return found; |
| 13 | } |
Explanation (EN)
A zero insertion count describes this writer only. A concurrent writer may have inserted the missing row, but this branch keeps the stale lookup and reports it absent.
Objašnjenje (HR)
Nula umetnutih redaka opisuje samo ovaj upis. Drugi upisivač možda je stvorio redak, ali ova grana zadržava stari rezultat i smatra ga odsutnim.
Good example
| 1 | type Catalog = { |
| 2 | find(ids: string[]): Promise<string[]>; |
| 3 | ensure(ids: string[]): Promise<number>; |
| 4 | }; |
| 5 |
|
| 6 | async function resolve(ids: string[], catalog: Catalog) { |
| 7 | let found = await catalog.find(ids); |
| 8 | const missing = ids.filter(id => !found.includes(id)); |
| 9 | if (missing.length > 0) { |
| 10 | await catalog.ensure(missing); |
| 11 | found = await catalog.find(ids); |
| 12 | } |
| 13 | return found; |
| 14 | } |
Explanation (EN)
After attempting to ensure missing records, resolve them again instead of inferring shared state from this request’s insert count.
Objašnjenje (HR)
Nakon pokušaja osiguravanja nedostajućih zapisa ponovno ih razriješi, umjesto zaključivanja o zajedničkom stanju iz broja umetanja ovog zahtjeva.
Notes (EN)
Use with create-if-absent or conflict-tolerant writes where concurrent callers can satisfy the same lookup. Database uniqueness and atomic conflict handling are still required. Re-reading does not itself make an unsafe insert atomic. Use a read with the visibility required by the operation and handle isolation or replica lag deliberately. If callers only need the attempt to finish, the helper can return void instead of constructing a success count solely to gate a follow-up lookup. For deliberately best-effort batches, log each failure with its item context and then resolve final state.
Bilješke (HR)
Koristi uz idempotentno stvaranje i upise koji toleriraju konflikt kada istodobni pozivatelji mogu zadovoljiti isti upit. I dalje su potrebni jedinstvenost u bazi i atomska obrada konflikta. Ponovno čitanje samo po sebi ne čini nesiguran insert atomskim. Čitanje mora imati potrebnu vidljivost, uz svjesnu obradu izolacije ili kašnjenja replike. Ako pozivatelju treba samo završetak pokušaja, helper može vratiti void umjesto broja uspjeha koji služi samo uvjetovanju ponovnog upita. U namjerno best-effort obradi zabilježi grešku uz pripadajuću stavku pa razriješi konačno stanje.
Exceptions / Tradeoffs (EN)
Insertion counts remain useful for metrics or behavior explicitly about rows created by this caller. A separate lookup is unnecessary when the atomic operation already returns a complete authoritative result, including existing records. Do not turn unrelated database failures into successful conflict handling or silently ignore required writes.
Iznimke / Tradeoffi (HR)
Broj umetanja i dalje je koristan za metrike ili ponašanje koje izričito ovisi o redcima ovog upisivača. Zaseban upit nije potreban kada atomska operacija već vraća potpun mjerodavan rezultat, uključujući postojeće zapise. Ne tretiraj nepovezane greške baze kao uspješan konflikt i ne ignoriraj obvezne upise.