@onlineapps/service-wrapper 2.0.8 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,218 @@
1
+ # Service Wrapper Architecture
2
+
3
+ > **NOTE: This document describes initial architecture concepts. For the production-ready decision, see [FINAL_ARCHITECTURE.md](./FINAL_ARCHITECTURE.md)**
4
+
5
+ ## Definition
6
+
7
+ Service Wrapper is a **collection of connectors** that provides all components necessary for a business service to function within the system.
8
+
9
+ ## Core Principles
10
+
11
+ 1. **Component Collection** - Wrapper is NOT a framework but a set of reusable components
12
+ 2. **Central Management** - All services use the same wrapper version for consistency
13
+ 3. **Version Independence** - Each service can pin its wrapper version as needed
14
+ 4. **Duplicate by Design** - Each service has its own wrapper instance (not shared)
15
+
16
+ ## Architecture Pattern: Enhanced Service
17
+
18
+ ```javascript
19
+ // Business service enhanced with wrapper components
20
+ const express = require('express');
21
+ const { MQConnector, MonitoringConnector, HealthConnector } = require('@onlineapps/service-wrapper');
22
+
23
+ class EnhancedService {
24
+ constructor() {
25
+ // Core business service
26
+ this.app = express();
27
+ this.setupBusinessRoutes();
28
+
29
+ // Wrapper components
30
+ this.mq = new MQConnector(this);
31
+ this.monitoring = new MonitoringConnector(this);
32
+ this.health = new HealthConnector(this);
33
+ }
34
+
35
+ async start() {
36
+ // 1. Start HTTP server
37
+ await this.app.listen(this.config.port);
38
+
39
+ // 2. Connect to MQ
40
+ await this.mq.connect();
41
+ await this.mq.consume('workflow.init', this.handleWorkflow.bind(this));
42
+ await this.mq.consume(`${this.config.name}.workflow`, this.handleServiceMessage.bind(this));
43
+
44
+ // 3. Start monitoring
45
+ await this.monitoring.start();
46
+
47
+ // 4. Register health checks
48
+ this.health.register('/health', this.checkHealth.bind(this));
49
+ }
50
+
51
+ handleWorkflow(message) {
52
+ // Wrapper handles workflow routing
53
+ const operation = this.config.operations[message.step.operation];
54
+
55
+ // Call own HTTP endpoint
56
+ return this.callHttp(operation.endpoint, message.input);
57
+ }
58
+
59
+ callHttp(endpoint, data) {
60
+ // Internal HTTP call to business logic
61
+ return fetch(`http://localhost:${this.config.port}${endpoint}`, {
62
+ method: 'POST',
63
+ body: JSON.stringify(data)
64
+ });
65
+ }
66
+ }
67
+ ```
68
+
69
+ ## Component Responsibilities
70
+
71
+ ### MQ Connector
72
+ - Listen on `workflow.init` queue
73
+ - Listen on service-specific queues
74
+ - Route messages between services
75
+ - Handle dead letter queues
76
+
77
+ ### Monitoring Connector
78
+ - Collect metrics
79
+ - Export to monitoring system
80
+ - Track request/response times
81
+ - Monitor queue depth
82
+
83
+ ### Health Connector
84
+ - Provide `/health` endpoint
85
+ - Check service dependencies
86
+ - Report readiness status
87
+ - Aggregate component health
88
+
89
+ ### Registry Connector
90
+ - Register service on startup
91
+ - Send heartbeat
92
+ - Update capabilities
93
+ - Handle deregistration
94
+
95
+ ## Single Process Architecture
96
+
97
+ **Decision:** Use single process with embedded wrapper components.
98
+
99
+ ### Rationale:
100
+ 1. **Simplicity** - One deployment unit
101
+ 2. **Efficiency** - No IPC overhead
102
+ 3. **Atomicity** - Components share state
103
+ 4. **Debugging** - Single log stream
104
+
105
+ ### Implementation:
106
+ ```javascript
107
+ // service/index.js
108
+ const ServiceWrapper = require('@onlineapps/service-wrapper');
109
+ const app = require('./src/app'); // Express app
110
+ const config = require('./conn-config/config.json');
111
+ const operations = require('./conn-config/operations.json');
112
+
113
+ // Single process startup
114
+ async function start() {
115
+ // Business service
116
+ const server = app.listen(config.port);
117
+
118
+ // Wrapper components
119
+ const wrapper = new ServiceWrapper({
120
+ app,
121
+ server,
122
+ config,
123
+ operations
124
+ });
125
+
126
+ await wrapper.initialize();
127
+ console.log(`Service ${config.name} running with wrapper components`);
128
+ }
129
+
130
+ start().catch(console.error);
131
+ ```
132
+
133
+ ## Configuration Pattern
134
+
135
+ ### operations.json
136
+ ```json
137
+ {
138
+ "operations": {
139
+ "operation-name": {
140
+ "endpoint": "/api/operation",
141
+ "method": "POST",
142
+ "input": { "schema": "..." },
143
+ "output": { "schema": "..." }
144
+ }
145
+ }
146
+ }
147
+ ```
148
+
149
+ ### config.json
150
+ ```json
151
+ {
152
+ "service": {
153
+ "name": "my-service",
154
+ "port": 3000
155
+ },
156
+ "wrapper": {
157
+ "mq": {
158
+ "url": "${RABBITMQ_URL}"
159
+ },
160
+ "monitoring": {
161
+ "enabled": true
162
+ }
163
+ }
164
+ }
165
+ ```
166
+
167
+ ## Health Check Strategy
168
+
169
+ Health checks are **provided by wrapper** but **implemented by service**:
170
+
171
+ ```javascript
172
+ // Wrapper provides endpoint
173
+ app.get('/health', healthConnector.handler);
174
+
175
+ // Service implements check
176
+ class MyService {
177
+ checkHealth() {
178
+ return {
179
+ status: this.isHealthy() ? 'healthy' : 'unhealthy',
180
+ database: this.db.isConnected(),
181
+ dependencies: this.checkDependencies()
182
+ };
183
+ }
184
+ }
185
+ ```
186
+
187
+ ## Migration Path
188
+
189
+ ### From Standalone Service:
190
+ 1. Add `@onlineapps/service-wrapper` dependency
191
+ 2. Create `conn-config/operations.json`
192
+ 3. Wrap service startup with ServiceWrapper
193
+ 4. Remove duplicate infrastructure code
194
+
195
+ ### From Two-Process Architecture:
196
+ 1. Merge wrapper.js into service index.js
197
+ 2. Remove separate wrapper process
198
+ 3. Consolidate configuration
199
+ 4. Single deployment unit
200
+
201
+ ## Benefits
202
+
203
+ 1. **No Duplication** - Common components in wrapper
204
+ 2. **Central Updates** - Update wrapper version for all services
205
+ 3. **Consistent Behavior** - All services work the same way
206
+ 4. **Simple Deployment** - One process per service
207
+ 5. **Clear Separation** - Business logic vs infrastructure
208
+
209
+ ## Drawbacks
210
+
211
+ 1. **Tight Coupling** - Service depends on wrapper version
212
+ 2. **Restart Required** - Any change restarts everything
213
+ 3. **Mixed Dependencies** - Business and infrastructure together
214
+ 4. **Testing Complexity** - Must mock wrapper components
215
+
216
+ ## Conclusion
217
+
218
+ Service Wrapper as a **component collection** in a **single process** provides the best balance of simplicity, efficiency, and maintainability for our microservices architecture.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlineapps/service-wrapper",
3
- "version": "2.0.8",
3
+ "version": "2.0.9",
4
4
  "description": "Thin orchestration layer for microservices - delegates all infrastructure concerns to specialized connectors",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -25,14 +25,14 @@
25
25
  "license": "MIT",
26
26
  "dependencies": {
27
27
  "@onlineapps/conn-base-cache": "^1.0.0",
28
- "@onlineapps/conn-base-monitoring": "file:../conn-base-monitoring/onlineapps-conn-base-monitoring-1.0.0.tgz",
28
+ "@onlineapps/conn-base-monitoring": "^1.0.0",
29
29
  "@onlineapps/conn-infra-error-handler": "^1.0.0",
30
30
  "@onlineapps/conn-infra-mq": "^1.1.0",
31
31
  "@onlineapps/conn-orch-api-mapper": "^1.0.0",
32
32
  "@onlineapps/conn-orch-cookbook": "^2.0.0",
33
33
  "@onlineapps/conn-orch-orchestrator": "^1.0.1",
34
34
  "@onlineapps/conn-orch-registry": "^1.1.4",
35
- "@onlineapps/monitoring-core": "file:../../../api/shared/monitoring-core/onlineapps-monitoring-core-1.0.0.tgz"
35
+ "@onlineapps/monitoring-core": "^1.0.0"
36
36
  },
37
37
  "devDependencies": {
38
38
  "express": "^5.1.0",