Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/audit-stores/community/couchbase-audit-store.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Couchbase
sidebar_position: 5
sidebar_position: 6
---

import Tabs from '@theme/Tabs';
Expand Down
2 changes: 1 addition & 1 deletion docs/audit-stores/community/dynamodb-audit-store.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: DynamoDB
sidebar_position: 4
sidebar_position: 5
---

import Tabs from '@theme/Tabs';
Expand Down
114 changes: 114 additions & 0 deletions docs/audit-stores/community/mongodb-reactive-audit-store.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
title: MongoDB Reactive
sidebar_position: 3
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# MongoDB Reactive Audit Store

The MongoDB reactive audit store (`MongoDBReactiveAuditStore`) enables Flamingock to record execution history and ensure safe coordination across distributed deployments using MongoDB as the storage backend, through the official MongoDB reactive streams driver.

> For a conceptual explanation of the audit store vs target systems, see [Audit store vs target system](../../get-started/audit-store-vs-target-system.md).

## Version compatibility

| Component | Version Requirement |
|----------------------------------|---------------------|
| MongoDB Reactive Streams Driver | 4.0.0+ |

MongoDB 4.0+ is recommended for optimal performance and feature support.

## Installation

Add the MongoDB reactive streams driver dependency to your project:

<Tabs groupId="gradle_maven">
<TabItem value="gradle" label="Gradle" default>
```kotlin
implementation("org.mongodb:mongodb-driver-reactivestreams:4.0.0")
```
</TabItem>
<TabItem value="maven" label="Maven">
```xml
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-reactivestreams</artifactId>
<version>4.0.0</version> <!-- 4.0.0+ supported -->
</dependency>
```
</TabItem>
</Tabs>

## Basic setup

Configure the audit store from a MongoDB reactive target system to get the connection configuration:

```java
var auditStore = MongoDBReactiveAuditStore.from(mongoDbReactiveTargetSystem);
```

A `MongoDBReactiveAuditStore` must be created from an existing target system that implements `MongoDBReactiveExternalSystem` - such as `MongoDBReactiveTargetSystem` or `MongoDBSpringDataReactiveTargetSystem`.

This ensures that both components point to the **same external MongoDB database**:

- The **Target System** applies your business changes.
- The **Audit Store** stores the execution history associated with those changes.

Internally, the Audit Store takes the Target System's underlying MongoDB database and creates its **own dedicated access handle**, keeping audit operations isolated while still referring to the same physical system.

> For a full conceptual explanation of this relationship, see
> **[Target Systems vs Audit Store](../../get-started/audit-store-vs-target-system.md)**.

Optional configurations can be added via `.withXXX()` methods.

:::info Register Audit Store
Once created, you need to register this audit store with Flamingock. See [Registering the community audit store](../introduction.md#registering-the-community-audit-store) for details.
:::

## Optional configuration (.withXXX() methods)

These configurations can be customized via `.withXXX()` methods with **no global context fallback**:

| Configuration | Method | Default | Description |
|--------------------------|-----------------------------------|--------------------------|-----------------------------------------|
| `Auto Create` | `.withAutoCreate(enabled)` | `true` | Auto-create collections and indexes |
| `WriteConcern` | `.withWriteConcern(concern)` | `MAJORITY` with journal | Write acknowledgment level |
| `ReadConcern` | `.withReadConcern(concern)` | `MAJORITY` | Read isolation level |
| `ReadPreference` | `.withReadPreference(pref)` | `PRIMARY` | Server selection for reads |
| `Audit Repository Name` | `.withAuditRepositoryName(name)` | `flamingockAuditLog` | Collection name for audit entries |
| `Lock Repository Name` | `.withLockRepositoryName(name)` | `flamingockLock` | Collection name for distributed locks |

**Important**: These default values are optimized for maximum consistency and should ideally be left unchanged. Override them only for testing purposes or exceptional cases.

## Configuration example

Here's a comprehensive example showing the configuration:

```java
// Create a MongoDB Reactive Target System
MongoDBReactiveTargetSystem mongoDbReactiveTargetSystem = new MongoDBReactiveTargetSystem("mongodb", mongoReactiveClient, auditDatabase);
// Audit store configuration (mandatory via constructor)
var auditStore = MongoDBReactiveAuditStore.from(mongoDbReactiveTargetSystem)
.withWriteConcern(WriteConcern.W1) // Optional configuration
.withReadPreference(ReadPreference.secondary()); // Optional configuration

// Register with Flamingock
Flamingock.builder()
.setAuditStore(auditStore)
.addTargetSystems(targetSystems...)
.build();
```

**Audit store configuration resolution:**
- **MongoDB reactive target system**: Must be provided via `from()` method. Gets the reactive `MongoDatabase` from the target system.
- **WriteConcern**: Uses explicit configuration instead of default
- **ReadPreference**: Uses explicit configuration instead of default

This architecture ensures explicit audit store configuration with no fallback dependencies.

## Next steps

- Learn about [Target systems](../../target-systems/introduction.md)
- 👉 See a [full example project](https://github.com/flamingock/flamingock-java-examples)
2 changes: 1 addition & 1 deletion docs/audit-stores/community/sql-audit-store.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: SQL
sidebar_position: 3
sidebar_position: 4
---

import Tabs from '@theme/Tabs';
Expand Down
1 change: 1 addition & 0 deletions docs/audit-stores/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ The audit store is **automatically provided and managed** by Flamingock Cloud. N
Alternatively, you can configure your own audit store using one of the supported databases:

- [MongoDB audit store](./community/mongodb-audit-store.md)
- [MongoDB Reactive audit store](./community/mongodb-reactive-audit-store.md)
- [DynamoDB audit store](./community/dynamodb-audit-store.md)
- [Couchbase audit store](./community/couchbase-audit-store.md)
- [SQL audit store](./community/sql-audit-store.md)
Expand Down
2 changes: 1 addition & 1 deletion docs/target-systems/couchbase-target-system.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Couchbase
sidebar_position: 6
sidebar_position: 8
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Expand Down
2 changes: 1 addition & 1 deletion docs/target-systems/dynamodb-target-system.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: DynamoDB
sidebar_position: 5
sidebar_position: 7
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Expand Down
2 changes: 2 additions & 0 deletions docs/target-systems/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ The standard choice for systems without native transaction support:
These implementations leverage native transaction capabilities for automatic rollback:

- [MongoDB target system](../target-systems/mongodb-target-system.md) - For MongoDB with the sync driver
- [MongoDB Reactive target system](../target-systems/mongodb-reactive-target-system.md) - For MongoDB with the reactive streams driver
- [MongoDB Spring Data target system](../target-systems/mongodb-springdata-target-system.md) - For MongoDB with Spring Data
- [MongoDB Spring Data Reactive target system](../target-systems/mongodb-springdata-reactive-target-system.md) - For MongoDB with reactive Spring Data
- [SQL target system](../target-systems/sql-target-system.md) - For relational databases (PostgreSQL, MySQL, etc.)
- [DynamoDB target system](../target-systems/dynamodb-target-system.md) - For Amazon DynamoDB
- [Couchbase target system](../target-systems/couchbase-target-system.md) - For Couchbase
Expand Down
156 changes: 156 additions & 0 deletions docs/target-systems/mongodb-reactive-target-system.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
---
title: MongoDB Reactive
sidebar_position: 4
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# MongoDB Reactive Target System

The MongoDB Reactive target system (`MongoDBReactiveTargetSystem`) enables Flamingock to apply changes to MongoDB databases using the official MongoDB reactive streams driver. As a transactional target system, it supports automatic rollback through MongoDB's native transaction capabilities.

## Version compatibility

| Component | Version Requirement |
|-----------|-------------------|
| MongoDB Reactive Streams Driver | 4.0.0+ |

MongoDB 4.0+ is required for transaction support.

## Installation

Add the MongoDB reactive streams driver dependency to your project (version 4.0.0+ required):

<Tabs groupId="gradle_maven">
<TabItem value="gradle" label="Gradle" default>
```kotlin
implementation("org.mongodb:mongodb-driver-reactivestreams:4.0.0")
```
</TabItem>
<TabItem value="maven" label="Maven">
```xml
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-reactivestreams</artifactId>
<version>4.0.0</version> <!-- 4.0.0+ supported -->
</dependency>
```
</TabItem>
</Tabs>

## Basic setup

Configure the target system:

```java
var mongoTarget = new MongoDBReactiveTargetSystem("user-database-id", mongoClient, "userDb");
```

The constructor requires the target system name, a reactive `MongoClient`, and the database name. Optional configurations can be added via `.withXXX()` methods.

:::info Register Target System
Once created, you need to register this target system with Flamingock. See [Registering target systems](introduction.md#registering-target-systems) for details.
:::

## Target System configuration

The MongoDB Reactive target system uses Flamingock's [split dependency resolution architecture](introduction.md#dependency-injection) with separate flows for target system configuration and change execution dependencies.

### Constructor dependencies (mandatory)

These dependencies must be provided at target system creation time with **no global context fallback**:

| Dependency | Constructor Parameter | Description |
|------------|----------------------|-------------|
| `MongoClient` (reactive) | `mongoClient` | Reactive MongoDB connection client - **required** for both target system configuration and change execution |
| `String` | `databaseName` | Target database name - **required** to identify which database changes will affect |

## Dependencies available to Changes

Changes can access dependencies through [dependency injection with fallback](../changes/anatomy-and-structure.md#method-parameters-and-dependency-injection):

1. **Target system context** (highest priority) - `MongoClient`, `MongoDatabase`, `ClientSession` (all from the reactive streams driver)
2. **Target system additional dependencies** - added via `.addDependency()` or `.setProperty()`
3. **Global context** (fallback) - shared dependencies available to all target systems

## Configuration example

Here's a comprehensive example showing the new architecture:

```java
// Target system configuration (mandatory via constructor)
var mongoTarget = new MongoDBReactiveTargetSystem("user-database", productionMongoClient, "userDb")
.addDependency(auditService); // Additional dependency for changes

// Global context with shared dependencies
Flamingock.builder()
.addDependency(emailService) // Available to all target systems
.addDependency(logService) // Available to all target systems
.addTargetSystems(mongoTarget)
.build();
```

**Target system configuration resolution:**
- **MongoClient**: Must be provided via constructor (`productionMongoClient`)
- **Database name**: Must be provided via constructor (`"userDb"`)

**Change dependency resolution for Changes in "user-database":**
- **MongoClient**: From target system context (`productionMongoClient`)
- **MongoDatabase**: From target system context (derived from `productionMongoClient` + `"userDb"`)
- **ClientSession**: From target system context (created by Flamingock)
- **AuditService**: From target system additional dependencies
- **EmailService**: From global context (fallback)
- **LogService**: From global context (fallback)

This architecture ensures explicit target system configuration while providing flexible dependency access for changes.

## Transactional support

For a Change to leverage MongoDB's transactional capabilities, it must use the reactive `ClientSession` parameter. Flamingock uses the injected `MongoClient` and `MongoDatabase` dependencies to create and manage this session's lifecycle - starting the transaction before execution, committing on success, and rolling back on failure.

> For detailed information on transaction handling, see [Transactions](../changes/transactions.md).

```java
@TargetSystem("user-database-id")
@Change(id = "create-users", author = "team") // order extracted from filename
public class _0001__CreateUsers {

@Apply
public void apply(MongoDatabase db, ClientSession session) {
// The reactive ClientSession is required for transactional execution
// Flamingock uses the target system's MongoClient to create this session
// and handles transaction start, commit, and rollback automatically
MongoCollection<Document> users = db.getCollection("users");
Publisher<InsertOneResult> insert = users.insertOne(session, new Document("name", "John"));

// The Change method runs synchronously from Flamingock's point of view, so the
// publisher must be awaited before returning - it won't execute on its own.
Mono.from(insert).block();
}
}
```

**How transactions work:**
1. **Session creation**: Flamingock uses the target system's reactive `MongoClient` to create a `ClientSession`
2. **Transaction management**: The same `MongoClient` and `MongoDatabase` handle transaction operations
3. **Lifecycle**: Flamingock automatically starts the transaction, commits on success, or rolls back on failure

Without the `ClientSession` parameter, operations will execute but won't participate in transactions.

:::info Reactive publishers must be consumed
The reactive streams driver returns `Publisher` objects that only execute once subscribed to - Flamingock does not subscribe to them for you. Every publisher produced inside a Change must be awaited before the method returns, so the operation actually completes within the Change's lifecycle and any failure surfaces synchronously (required for Flamingock to catch it and trigger rollback).

The example above uses Project Reactor's `Mono.from(publisher).block()`, since Reactor is already a common dependency in reactive stacks (and a hard requirement for the [Spring Data Reactive target system](mongodb-springdata-reactive-target-system.md)). If you'd rather not add Reactor as a dependency, subscribe with your own `Subscriber` (or RxJava's `Flowable.fromPublisher(...)`) and block until `onComplete`/`onError`.
:::

## Available dependencies in Changes

Your Changes can inject MongoDB reactive-specific dependencies like `MongoClient`, `MongoDatabase`, and `ClientSession` (for transactions), but are not limited to these. The target system provides these dependencies through its context, and you can add additional dependencies via `.addDependency()` that take precedence over global dependencies.

For comprehensive details on change dependency resolution, see [Change Anatomy & Structure](../changes/anatomy-and-structure.md).

## Next steps

- Learn about [Target systems](introduction.md)
- Explore [Changes](../changes/introduction.md)
- See [Flamingock examples](https://github.com/flamingock/flamingock-java-examples)
Loading