|
| 1 | +# ADR: Replace Common Settings HTTP API with RabbitMQ Publishing |
| 2 | + |
| 3 | +## Status |
| 4 | + |
| 5 | +**Proposed** |
| 6 | + |
| 7 | +## Context |
| 8 | + |
| 9 | +The cozy-stack currently synchronizes user settings with an external "common settings" application via HTTP API calls. |
| 10 | +This integration is implemented in `model/settings/common/common.go` and performs: |
| 11 | + |
| 12 | +1. **HTTP POST** to `/api/admin/user/settings` when creating settings |
| 13 | +2. **HTTP GET** to `/api/admin/user/settings/{nickname}` to check remote version |
| 14 | +3. **HTTP PUT** to `/api/admin/user/settings/{nickname}` to update settings |
| 15 | + |
| 16 | +This approach has several issues: |
| 17 | + |
| 18 | +- **Synchronous blocking**: HTTP calls block the settings update operation |
| 19 | +- **Version conflict complexity**: The code checks remote versions before updates, creating complex conflict resolution logic |
| 20 | +- **Tight coupling**: Direct HTTP dependency on the common settings app |
| 21 | +- **Failure propagation**: HTTP failures can affect the main settings update flow |
| 22 | +- **No longer needed**: The common settings app is no longer actively updating settings, making version conflict checking obsolete |
| 23 | + |
| 24 | +The codebase already has a mature RabbitMQ infrastructure for message consumption (password updates, user creation, phone updates, subscription changes, app lifecycle). |
| 25 | +This infrastructure can be extended for publishing. |
| 26 | + |
| 27 | +## Proposal |
| 28 | + |
| 29 | +Replace the HTTP API calls with RabbitMQ message publishing using a fire-and-forget pattern: |
| 30 | + |
| 31 | +### Architecture |
| 32 | + |
| 33 | +```mermaid |
| 34 | +flowchart LR |
| 35 | + subgraph CozyStack["cozy-stack"] |
| 36 | + Publisher["Publisher"] |
| 37 | + end |
| 38 | +
|
| 39 | + subgraph Storage["Storage"] |
| 40 | + CouchDB["CouchDB<br/>(settings)"] |
| 41 | + end |
| 42 | +
|
| 43 | + subgraph MessageBroker["Message Broker"] |
| 44 | + RabbitMQ["RabbitMQ<br/>(exchange: settings)"] |
| 45 | + end |
| 46 | +
|
| 47 | + subgraph Consumer["TWP app"] |
| 48 | + CommonSettings["Common Settings<br/>(consume)"] |
| 49 | + end |
| 50 | +
|
| 51 | + Publisher -->|"1. Update settings"| CouchDB |
| 52 | + Publisher -->|"2. Publish message"| RabbitMQ |
| 53 | + RabbitMQ -->|"user.settings.updated"| CommonSettings |
| 54 | +``` |
| 55 | + |
| 56 | +### Key Changes |
| 57 | + |
| 58 | +1. **New Publisher Infrastructure** (`pkg/rabbitmq/publisher.go`) |
| 59 | + - Reuses existing `RabbitMQConnection` for connection management |
| 60 | + - Provides thread-safe publishing with automatic channel recovery |
| 61 | + - JSON serialization with persistent delivery mode |
| 62 | + |
| 63 | +2. **Service Layer Extension** (`pkg/rabbitmq/service.go`) |
| 64 | + - Add publishing capabilities alongside existing consumers |
| 65 | + - Context-aware publisher selection (same as consumers) |
| 66 | + |
| 67 | +3. **Simplified Common Settings Module** (`model/settings/common/common.go`) |
| 68 | + - Replace HTTP calls with RabbitMQ publishing |
| 69 | + - Remove version conflict checking (local DB is source of truth) |
| 70 | + - Fire-and-forget: log errors but don't fail the operation |
| 71 | + |
| 72 | +### Configuration |
| 73 | + |
| 74 | +```yaml |
| 75 | +rabbitmq: |
| 76 | + enabled: true |
| 77 | + nodes: |
| 78 | + default: |
| 79 | + url: amqp://guest:guest@localhost:5672/ |
| 80 | + publishing: |
| 81 | + common_settings: |
| 82 | + exchange: "settings" |
| 83 | + routing_key: "user.settings.updated" |
| 84 | +``` |
| 85 | +
|
| 86 | +### Message Format |
| 87 | +
|
| 88 | +Preserve existing message structure for backward compatibility: |
| 89 | +
|
| 90 | +```json |
| 91 | +{ |
| 92 | + "source": "cozy-stack", |
| 93 | + "nickname": "user-slug", |
| 94 | + "request_id": "domain_1234567890", |
| 95 | + "timestamp": 1234567890, |
| 96 | + "version": 2, |
| 97 | + "payload": { |
| 98 | + "language": "en", |
| 99 | + "timezone": "Europe/Paris", |
| 100 | + "first_name": "John", |
| 101 | + "last_name": "Doe", |
| 102 | + "display_name": "John Doe", |
| 103 | + "email": "john@example.com", |
| 104 | + "phone": "+33612345678", |
| 105 | + "matrix_id": "@john:example.com", |
| 106 | + "avatar": "https://cozy.example.com/public/avatar?v=2" |
| 107 | + } |
| 108 | +} |
| 109 | +``` |
| 110 | + |
| 111 | +## Alternatives |
| 112 | + |
| 113 | +## Decision |
| 114 | + |
| 115 | +## Consequences |
| 116 | + |
0 commit comments