diff --git a/GEMINI.md b/GEMINI.md index adc2593..c49f80c 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -18,7 +18,7 @@ The extension exposes the following functions to PostgreSQL: ### `cache_json_schemas(enums jsonb, types jsonb, puncs jsonb) -> jsonb` -Loads and compiles the entire schema registry into the session's memory. +Loads and compiles the entire schema registry into the session's memory, atomically replacing the previous validator. * **Inputs**: * `enums`: Array of enum definitions. @@ -80,7 +80,6 @@ JSPG enforces a "Secure by Default" philosophy. All schemas are treated as if `u * **Ref Boundaries**: Strictness is reset when crossing `$ref` boundaries. The referenced schema's strictness is determined by its own definition (strict by default unless `extensible: true`), ignoring the caller's state. * **Inheritance**: Strictness is inherited. A schema extending a strict parent will also be strict unless it declares itself `extensible: true`. Conversely, a schema extending a loose parent will also be loose unless it declares itself `extensible: false`. - ### 4. Format Leniency for Empty Strings To simplify frontend form logic, the format validators for `uuid`, `date-time`, and `email` explicitly allow empty strings (`""`). This treats an empty string as "present but unset" rather than "invalid format". @@ -92,8 +91,18 @@ The extension is written in Rust using `pgrx` and structures its schema parser t * **Compiler Phase**: schema JSONs are parsed into this struct, linked (references resolved), and then compiled into an efficient validation tree. * **Validation Phase**: The compiled validators traverse the JSON instance using `serde_json::Value`. +### Concurrency & Threading ("Atomic Swap") + +To support high-throughput validation while allowing for runtime schema updates (e.g., during development or hot-reloading), JSPG uses an **Atomic Swap** pattern. + +1. **Immutable Validator**: The `Validator` struct immutably owns the `Registry`. Once created, a validator instance (and its registry) never changes. +2. **Global Pointer**: A global `RwLock>>` holds the current active validator. +3. **Lock-Free Reads**: Validation requests acquire a read lock just long enough to clone the `Arc` (incrementing a reference count), then release the lock immediately. Validation proceeds on the snapshot, ensuring no blocking during schema updates. +4. **Atomic Updates**: When schemas are reloaded (`cache_json_schemas`), a new `Registry` and `Validator` are built entirely on the stack. The global pointer is then atomically swapped to the new instance under a write lock. + ## 🧪 Testing Testing is driven by standard Rust unit tests that load JSON fixtures. -The tests are located in `tests/fixtures/*.json` and are executed via `cargo test`. \ No newline at end of file +* **Isolation**: Each test file runs with its own isolated `Registry` and `Validator` instance, created on the stack. This eliminates global state interference and allows tests to run in parallel. +* **Fixtures**: The tests are located in `tests/fixtures/*.json` and are executed via `cargo test`. \ No newline at end of file