diff --git a/flash-extensions/flash-ext-data-core/docs/README.md b/flash-extensions/flash-ext-data-core/docs/README.md index 0454c12..df53379 100644 --- a/flash-extensions/flash-ext-data-core/docs/README.md +++ b/flash-extensions/flash-ext-data-core/docs/README.md @@ -1,93 +1,93 @@ # flash-ext-data-core -Core comune per il layer dati di Flash. +Shared core for Flash's data layer. -## Scopo +## Purpose -Questo modulo definisce il contratto transazionale condiviso tra le implementazioni backend. -Non parla con Hibernate o JDBC direttamente: espone solo astrazioni e un runtime minimale. +This module defines the transactional contract shared across backend implementations. It does not +talk to Hibernate or JDBC directly: it exposes abstractions and a minimal runtime, nothing else. -## Componenti +## Components -- `TxDefinition`: metadata immutabile della transazione. -- `TxStatus`: stato runtime restituito dal manager. -- `TxManager`: contratto per `begin`, `commit`, `rollback`. -- `Tx`: orchestration runtime e stack transazionale per thread. -- `ResourceRegistry`: storage thread-local di risorse e synchronizations. -- `Repository`: base repository auto-transazionale. -- `Spec`: predicato componibile. -- `Query`: oggetto query con spec, sort e paging. -- `SpecBuilder`: DSL fluente per costruire spec tipizzate. -- `RepositorySupport`: helper interno condiviso. -- `TransactionPropagation`: semantica di propagazione. -- `TransactionIsolation`: livello di isolamento. -- `TxSynchronization`: hook lifecycle (vedi sotto). +- `TxDefinition`: immutable transaction metadata. +- `TxStatus`: runtime state returned by the manager. +- `TxManager`: the `begin`/`commit`/`rollback` contract. +- `Tx`: runtime orchestration and the per-thread transaction stack. +- `ResourceRegistry`: thread-local storage for resources and synchronizations. +- `Repository`: self-transactional base repository. +- `Spec`: composable predicate. +- `Query`: query object carrying spec, sort and paging. +- `SpecBuilder`: fluent DSL for building typed specs. +- `RepositorySupport`: shared internal helper. +- `TransactionPropagation`: propagation semantics. +- `TransactionIsolation`: isolation level. +- `TxSynchronization`: lifecycle hooks (see below). -## Modello di esecuzione +## Execution model -Il flusso è: +The flow is: -1. `Tx.call(definition, work)` chiama `TxManager.begin(definition)`. -2. Il `TxManager` crea un `TxStatus` backend-specific. -3. Lo status viene pushato nello stack thread-local. -4. Il lavoro usa `Tx.resource(Class)` per ottenere la risorsa corrente. -5. A fine lavoro `Tx` decide tra `commit` e `rollback`. -6. Lo stack viene poppato e il thread-local viene pulito se vuoto. +1. `Tx.call(definition, work)` calls `TxManager.begin(definition)`. +2. The `TxManager` creates a backend-specific `TxStatus`. +3. The status is pushed onto the thread-local stack. +4. The work uses `Tx.resource(Class)` to obtain the current resource. +5. When the work ends, `Tx` chooses between `commit` and `rollback`. +6. The stack is popped, and the thread-local is cleared once it is empty. -## Propagation supportata +## Supported propagation -- `REQUIRED`: usa la tx attiva oppure ne apre una nuova. -- `REQUIRES_NEW`: sospende la tx corrente e apre una nuova tx. -- `SUPPORTS`: se esiste una tx attiva si aggancia, altrimenti esegue senza tx. -- `NOT_SUPPORTED`: sospende la tx corrente ed esegue senza tx. -- `MANDATORY`: richiede una tx attiva. +- `REQUIRED`: use the active transaction, or open a new one. +- `REQUIRES_NEW`: suspend the current transaction and open a new one. +- `SUPPORTS`: join the active transaction if there is one, otherwise run without a transaction. +- `NOT_SUPPORTED`: suspend the current transaction and run without one. +- `MANDATORY`: require an active transaction. -## Synchronization (`TxSynchronization`) +## Synchronizations (`TxSynchronization`) -Hook sul ciclo di vita di **una** transazione, registrati con `Data.afterCommit(...)` (o -direttamente con `ResourceRegistry.addSynchronization(...)`). +Lifecycle hooks for **one** transaction, registered through `Data.afterCommit(...)` (or directly +with `ResourceRegistry.addSynchronization(...)`). -Ogni callback appartiene esattamente alla transazione più interna attiva al momento della -registrazione, e scatta una volta sola quando *quella* transazione completa: +Every callback belongs to exactly the innermost transaction active at registration time, and fires +exactly once, when *that* transaction completes: -- una tx interna **joined** (`REQUIRED`) non è una transazione a sé, quindi i callback registrati - al suo interno aspettano il commit più esterno; -- una tx `REQUIRES_NEW` lo è, quindi completarla fa scattare solo i propri callback e lascia in - sospeso quelli della transazione esterna sospesa. +- a **joined** inner transaction (`REQUIRED`) is not a transaction of its own, so callbacks + registered inside one wait for the outermost commit; +- a `REQUIRES_NEW` transaction is, so completing it fires only its own callbacks and leaves the + suspended outer transaction's pending. -### Posizione rispetto al commit +### Which side of the commit each hook sits on -| hook | quando | risorsa | +| hook | when | resource | | --- | --- | --- | -| `beforeCommit(readOnly)` | subito **prima** del commit reale | sessione/connection ancora **bound**, tx ancora attiva | -| `afterCommit()` / `afterRollback()` | dopo il completamento | risorsa già **sganciata** | -| `afterCompletion(outcome)` | dopo i due precedenti | risorsa già sganciata | +| `beforeCommit(readOnly)` | immediately **before** the real commit | session/connection still **bound**, transaction still active | +| `afterCommit()` / `afterRollback()` | after completion | resource already **unbound** | +| `afterCompletion(outcome)` | after the two above | resource already unbound | -`beforeCommit` è l'unico hook che può ancora scrivere sulla stessa risorsa e finire nella stessa -unità atomica: flush di un buffer, riga di audit, valore derivato. Non viene eseguito se la -transazione è già `rollback-only`, perché non c'è nessun commit da precedere. +`beforeCommit` is the only hook that can still write through the same resource and have the write +land in the same atomic unit: flush a buffer, stamp an audit row, materialize a derived value. It +is skipped when the transaction is already `rollback-only`, since there is no commit to precede. -I callback post-completamento girano invece a risorsa sganciata: uno che apre una propria -transazione ne ottiene una **nuova** invece di agganciarsi a quella appena conclusa. È questo che -li rende il posto giusto per invalidare una cache, accodare un messaggio o notificare qualcosa -fuori dal database. +Post-completion callbacks run with the resource unbound instead: one that opens its own transaction +gets a **fresh** one rather than joining the transaction that just finished. That is what makes +them the right place to refresh a cache, enqueue a message, or notify anything outside the +database. -### Fallimenti +### Failure -Lanciare da `beforeCommit` **veta il commit**: la transazione va in rollback, scattano -`afterRollback`/`afterCompletion(ROLLED_BACK)` e l'eccezione arriva al chiamante. È il motivo per -cui l'hook gira prima del commit e non dopo — può ancora rifiutare. +Throwing from `beforeCommit` **vetoes the commit**: the transaction is rolled back, +`afterRollback`/`afterCompletion(ROLLED_BACK)` fire, and the exception reaches the caller. That is +the reason the hook runs before the commit rather than after — it can still refuse. -Gli hook post-completamento non hanno questo potere: la transazione è già chiusa quando girano, -quindi un'eccezione si propaga ma non cambia nulla di ciò che è stato committato, e blocca i -callback in coda dietro di lei. +The post-completion hooks have no such power: the transaction is already over by the time they run, +so an exception propagates but changes nothing already committed, and stops the callbacks queued +behind it. -## Uso di `Repository` +## Using `Repository` -`Repository` è la base comune per le repository concrete. -Ogni operazione pubblica usa internamente una tx `REQUIRED` o `REQUIRED` read-only. +`Repository` is the shared base for concrete repositories. Every public operation internally uses a +`REQUIRED` transaction, read-only where applicable. -Le sottoclassi implementano i metodi `doXxx(...)` del nuovo modello: +Subclasses implement the `doXxx(...)` methods: - `doFind(Query)` - `doFindOne(Spec)` @@ -95,7 +95,8 @@ Le sottoclassi implementano i metodi `doXxx(...)` del nuovo modello: - `doDeleteAll(Spec)` - `doUpdateAll(Spec, T)` -I vecchi overload di `findAll(...)` e `findPage(...)` sono stati ridotti a una combinazione di `Query` e `Spec`. +The old `findAll(...)` and `findPage(...)` overloads were reduced to a combination of `Query` and +`Spec`. ```java public abstract class Repository { @@ -104,21 +105,21 @@ public abstract class Repository { } ``` -## Composizione con Flash +## Composing with Flash -`DataExtension` registra: +`DataExtension` registers: -- `Tx` nel `FlashContext` -- `TxManager` nel `FlashContext` -- un annotation processor per `@Transactional` +- `Tx` in the `FlashContext` +- `TxManager` in the `FlashContext` +- an annotation processor for `@Transactional` -Questo rende il layer dati componibile con il sistema di extension di Flash senza stato globale. +This makes the data layer composable with Flash's extension system without global state. -## Note implementative +## Implementation notes -- Lo stack transazionale è thread-local e viene ripulito quando torna vuoto. -- Le risorse backend sono sospese e ripristinate per `REQUIRES_NEW` e `NOT_SUPPORTED`. -- `TxSynchronization` è il punto di aggancio per hook di commit/rollback/completion. -- Le synchronization sono in una lista thread-local; ogni transazione nuova registra quante ne - esistevano già alla sua apertura e fa scattare solo la propria coda, così una `REQUIRES_NEW` - non trascina con sé quelle della transazione sospesa. +- The transaction stack is thread-local and is cleared once it becomes empty. +- Backend resources are suspended and restored for `REQUIRES_NEW` and `NOT_SUPPORTED`. +- `TxSynchronization` is the hook point for commit/rollback/completion callbacks. +- Synchronizations live in a thread-local list; every new transaction records how many were already + registered when it opened and fires only its own tail, so a `REQUIRES_NEW` does not drag along + the suspended transaction's callbacks. diff --git a/flash-extensions/flash-ext-data-hibernate/docs/README.md b/flash-extensions/flash-ext-data-hibernate/docs/README.md index 5264a02..5854b6a 100644 --- a/flash-extensions/flash-ext-data-hibernate/docs/README.md +++ b/flash-extensions/flash-ext-data-hibernate/docs/README.md @@ -1,14 +1,15 @@ # flash-ext-data-hibernate -Backend Hibernate per `flash-ext-data-core`. +Hibernate backend for `flash-ext-data-core`. -## Scopo +## Purpose -Questo modulo implementa `TxManager` sopra `SessionFactory` e fornisce una base repository Hibernate-centric. +This module implements `TxManager` on top of a `SessionFactory` and provides a Hibernate-centric +repository base class. -## Come si usa +## How to use it -### 1. Creare il manager +### 1. Create the manager ```java SessionFactory sessionFactory = ...; @@ -16,12 +17,12 @@ HibernateTxManager txManager = new HibernateTxManager(sessionFactory); DataExtension extension = new DataExtension(txManager); ``` -### 2. Installare l’estensione in Flash +### 2. Install the extension in Flash -L’estensione registra `Tx` e `TxManager` nel `FlashContext`. -Le handler class-based annotate con `@Transactional` vengono wrappate automaticamente. +The extension registers `Tx` and `TxManager` in the `FlashContext`. Class-based handlers annotated +with `@Transactional` are wrapped automatically. -### 3. Definire una repository +### 3. Define a repository ```java public final class UserRepository extends HibernateRepository { @@ -31,7 +32,7 @@ public final class UserRepository extends HibernateRepository { } ``` -Con il nuovo modello query/spec puoi esporre campi riusabili come costanti: +With the query/spec model you can expose reusable fields as constants: ```java public final class UserRepository extends HibernateRepository { @@ -48,7 +49,7 @@ public final class UserRepository extends HibernateRepository { } ``` -Le query domain-specific possono usare gli helper della base class: +Domain-specific queries can use the base class helpers: ```java public List findByEmailDomain(String domain) { @@ -58,35 +59,37 @@ public List findByEmailDomain(String domain) { } ``` -## Come funziona sotto +## How it works underneath -- La tx corrente è rappresentata da `HibernateTxStatus`. -- La risorsa esposta al core è una `Session`. -- `Tx.resource(Session.class)` recupera la `Session` dal contesto corrente. -- `REQUIRES_NEW` sospende lo status attivo e apre una nuova `Session`. -- `NOT_SUPPORTED` sospende la tx attiva e continua senza sessione bindata. +- The current transaction is represented by `HibernateTxStatus`. +- The resource exposed to the core is a `Session`. +- `Tx.resource(Session.class)` retrieves the `Session` from the current context. +- `REQUIRES_NEW` suspends the active status and opens a new `Session`. +- `NOT_SUPPORTED` suspends the active transaction and continues with no session bound. -## Repository base +## Repository base class -`HibernateRepository` fornisce: +`HibernateRepository` provides: - `findById`, `findAll`, `findPage`, `findOne` - `save`, `update`, `delete`, `saveAll` -- bulk `deleteAll(Spec)` e `updateAll(Spec, T)` -- helper HQL: `hql(...)`, `hqlMutate(...)` +- bulk `deleteAll(Spec)` and `updateAll(Spec, T)` +- HQL helpers: `hql(...)`, `hqlMutate(...)` -Le classi concrete devono solo implementare query di dominio, non il plumbing transazionale. +Concrete classes only have to implement domain queries, never the transactional plumbing. -## Semantica transazionale +## Transactional semantics -- `REQUIRED`: join o apertura nuova tx. -- `REQUIRES_NEW`: sospensione del contesto corrente. -- `SUPPORTS`: join se c’è tx, altrimenti no-op. -- `NOT_SUPPORTED`: sospende e prosegue senza tx. -- `MANDATORY`: fallisce se non c’è tx. +- `REQUIRED`: join, or open a new transaction. +- `REQUIRES_NEW`: suspend the current context. +- `SUPPORTS`: join if a transaction exists, otherwise no-op. +- `NOT_SUPPORTED`: suspend and continue without a transaction. +- `MANDATORY`: fail if there is no transaction. -## Note +## Notes -- `Session` viene chiusa a fine tx nuova. -- Le synchronizations vengono eseguite al commit/rollback. -- Il backend è pensato per essere usato tramite la base class, non direttamente. +- The `Session` is closed when a new transaction ends. +- Synchronizations registered in a transaction fire when *that* transaction completes: + `beforeCommit` while it is still active and the `Session` still bound, the post-completion hooks + once it is unbound. See `flash-ext-data-core/docs/README.md` for the full contract. +- This backend is meant to be used through the base class, not directly. diff --git a/flash-extensions/flash-ext-data-jdbc/docs/README.md b/flash-extensions/flash-ext-data-jdbc/docs/README.md index 62e9cd4..fd3b4cb 100644 --- a/flash-extensions/flash-ext-data-jdbc/docs/README.md +++ b/flash-extensions/flash-ext-data-jdbc/docs/README.md @@ -1,14 +1,15 @@ # flash-ext-data-jdbc -Backend JDBC per `flash-ext-data-core`. +JDBC backend for `flash-ext-data-core`. -## Scopo +## Purpose -Questo modulo implementa `TxManager` sopra `DataSource` e fornisce una base repository SQL raw. +This module implements `TxManager` on top of a `DataSource` and provides a raw-SQL repository base +class. -## Come si usa +## How to use it -### 1. Creare il manager +### 1. Create the manager ```java DataSource dataSource = ...; @@ -16,11 +17,12 @@ JdbcTxManager txManager = new JdbcTxManager(dataSource); DataExtension extension = new DataExtension(txManager); ``` -### 2. Installare l’estensione in Flash +### 2. Install the extension in Flash -Come per Hibernate, `DataExtension` registra `Tx` nel `FlashContext` e abilita `@Transactional` sugli handler class-based. +As with Hibernate, `DataExtension` registers `Tx` in the `FlashContext` and enables +`@Transactional` on class-based handlers. -### 3. Definire una repository +### 3. Define a repository ```java public final class UserRepository extends JdbcRepository { @@ -35,7 +37,7 @@ public final class UserRepository extends JdbcRepository { } ``` -Anche qui puoi esporre `Spec` riusabili e comporre query dal service layer: +Here too you can expose reusable `Spec`s and compose queries from the service layer: ```java public final class UserRepository extends JdbcRepository { @@ -47,7 +49,7 @@ public final class UserRepository extends JdbcRepository { } ``` -Per il salvataggio e l’update devi fornire il binding esplicito: +Saving and updating need an explicit binding: ```java @Override @@ -61,36 +63,39 @@ protected void bindInsert(PreparedStatement ps, User entity) throws SQLException } ``` -## Come funziona sotto +## How it works underneath -- La tx corrente espone una `Connection`. -- `Tx.resource(Connection.class)` recupera la connessione bindata al thread. -- `REQUIRES_NEW` sospende la connessione attiva e ne apre una nuova. -- `NOT_SUPPORTED` sospende il contesto e prosegue senza tx. +- The current transaction exposes a `Connection`. +- `Tx.resource(Connection.class)` retrieves the connection bound to the thread. +- `REQUIRES_NEW` suspends the active connection and opens a new one. +- `NOT_SUPPORTED` suspends the context and continues without a transaction. -## Repository base +## Repository base class -`JdbcRepository` fornisce: +`JdbcRepository` provides: -- query `select` con `queryOne`, `queryMany` -- mutation con `mutate` -- persistenza con `doSave`, `doUpdate` -- paging con `doFindPage` +- `select` queries through `queryOne`, `queryMany` +- mutations through `mutate` +- persistence through `doSave`, `doUpdate` +- paging through `doFindPage` - bulk `deleteAll(Spec)` -- helper raw `queryOne(...)`, `queryMany(...)`, `mutate(...)` +- raw helpers `queryOne(...)`, `queryMany(...)`, `mutate(...)` -Le repository concrete devono solo tradurre tra `ResultSet` e dominio. +Concrete repositories only have to translate between `ResultSet` and the domain. -## Semantica transazionale +## Transactional semantics -- `REQUIRED`: join o apertura nuova tx. -- `REQUIRES_NEW`: sospensione del contesto corrente. -- `SUPPORTS`: join se c’è tx, altrimenti no-op. -- `NOT_SUPPORTED`: sospende e prosegue senza tx. -- `MANDATORY`: fallisce se non c’è tx. +- `REQUIRED`: join, or open a new transaction. +- `REQUIRES_NEW`: suspend the current context. +- `SUPPORTS`: join if a transaction exists, otherwise no-op. +- `NOT_SUPPORTED`: suspend and continue without a transaction. +- `MANDATORY`: fail if there is no transaction. -## Note +## Notes -- La `Connection` viene chiusa a fine tx nuova. -- Le synchronizations vengono eseguite al commit/rollback. -- Se una repository usa `doDelete(T)`, il comportamento predefinito è non supportato: usare `deleteById` o override specifico. +- The `Connection` is closed when a new transaction ends. +- Synchronizations registered in a transaction fire when *that* transaction completes: + `beforeCommit` while it is still active and the `Connection` still bound, the post-completion + hooks once it is unbound. See `flash-ext-data-core/docs/README.md` for the full contract. +- If a repository uses `doDelete(T)`, the default behaviour is unsupported: use `deleteById` or + override it.