@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.
- package/README.md +66 -39
- package/docs/ARCHITECTURE_DECISION.md +200 -0
- package/docs/FINAL_ARCHITECTURE.md +271 -0
- package/docs/HANDLER_VS_HTTP_COMPARISON.md +269 -0
- package/docs/INSTALLATION_GUIDE.md +353 -0
- package/docs/OPERATIONS_SCHEMA.md +43 -1
- package/docs/WRAPPER_ARCHITECTURE.md +218 -0
- package/onlineapps-service-wrapper-2.0.8.tgz +0 -0
- package/package.json +3 -3
- package/src/ServiceWrapper.js +432 -273
package/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# @onlineapps/service-wrapper
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Collection of connectors providing all infrastructure components for business services**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Service Wrapper is a set of reusable connector components that handle message queue operations, service registration, monitoring, and health checks for microservices in a single-process architecture.
|
|
6
|
+
|
|
7
|
+
> **For complete architecture documentation, see [docs/FINAL_ARCHITECTURE.md](./docs/FINAL_ARCHITECTURE.md)**
|
|
6
8
|
|
|
7
9
|
## Naming Convention
|
|
8
10
|
|
|
@@ -41,32 +43,43 @@ This package provides the infrastructure layer that sits between:
|
|
|
41
43
|
|
|
42
44
|
## Usage
|
|
43
45
|
|
|
44
|
-
### 1.
|
|
46
|
+
### 1. Install Service Wrapper
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install @onlineapps/service-wrapper
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Create Service Entry Point
|
|
45
53
|
|
|
46
54
|
```javascript
|
|
47
|
-
|
|
55
|
+
// index.js
|
|
48
56
|
const express = require('express');
|
|
57
|
+
const { ServiceWrapper } = require('@onlineapps/service-wrapper');
|
|
49
58
|
|
|
50
|
-
//
|
|
51
|
-
const app =
|
|
52
|
-
app.get('/hello', (req, res) => {
|
|
53
|
-
res.json({ message: `Hello ${req.query.name}` });
|
|
54
|
-
});
|
|
59
|
+
// Load your Express app (business logic only)
|
|
60
|
+
const app = require('./src/app');
|
|
55
61
|
|
|
56
|
-
//
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
// Load configuration
|
|
63
|
+
const config = require('./conn-config/config.json');
|
|
64
|
+
const operations = require('./conn-config/operations.json');
|
|
65
|
+
|
|
66
|
+
async function start() {
|
|
67
|
+
// 1. Start Express server
|
|
68
|
+
const server = app.listen(process.env.PORT || 3000);
|
|
69
|
+
|
|
70
|
+
// 2. Initialize wrapper components
|
|
71
|
+
const wrapper = new ServiceWrapper({
|
|
72
|
+
app,
|
|
73
|
+
server,
|
|
74
|
+
config,
|
|
75
|
+
operations
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
await wrapper.initialize();
|
|
79
|
+
console.log('Service ready with all infrastructure components');
|
|
80
|
+
}
|
|
67
81
|
|
|
68
|
-
|
|
69
|
-
wrapper.start();
|
|
82
|
+
start().catch(console.error);
|
|
70
83
|
```
|
|
71
84
|
|
|
72
85
|
### 2. Service Receives
|
|
@@ -88,25 +101,37 @@ NO infrastructure code needed in your service!
|
|
|
88
101
|
|
|
89
102
|
## Configuration
|
|
90
103
|
|
|
91
|
-
|
|
104
|
+
### operations.json
|
|
105
|
+
```json
|
|
92
106
|
{
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
port: 3000, // Service port
|
|
101
|
-
healthPath: '/health', // Health check path
|
|
102
|
-
retryPolicy: { // Retry configuration
|
|
103
|
-
maxRetries: 3,
|
|
104
|
-
backoffMs: 1000
|
|
107
|
+
"operations": {
|
|
108
|
+
"operation-name": {
|
|
109
|
+
"description": "Operation description",
|
|
110
|
+
"endpoint": "/api/operation",
|
|
111
|
+
"method": "POST",
|
|
112
|
+
"input": { "name": { "type": "string", "required": true } },
|
|
113
|
+
"output": { "result": { "type": "string" } }
|
|
105
114
|
}
|
|
106
115
|
}
|
|
107
116
|
}
|
|
108
117
|
```
|
|
109
118
|
|
|
119
|
+
### config.json
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"service": {
|
|
123
|
+
"name": "my-service",
|
|
124
|
+
"port": 3000
|
|
125
|
+
},
|
|
126
|
+
"wrapper": {
|
|
127
|
+
"mq": { "url": "${RABBITMQ_URL}" },
|
|
128
|
+
"registry": { "url": "${REGISTRY_URL}" },
|
|
129
|
+
"monitoring": { "enabled": true },
|
|
130
|
+
"health": { "endpoint": "/health" }
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
110
135
|
## What This Handles
|
|
111
136
|
|
|
112
137
|
### Workflow Processing
|
|
@@ -144,12 +169,14 @@ Your service should NOT have:
|
|
|
144
169
|
```
|
|
145
170
|
my-service/
|
|
146
171
|
├── src/
|
|
147
|
-
│ ├──
|
|
172
|
+
│ ├── app.js # Express app (business logic only)
|
|
148
173
|
│ ├── routes/ # API endpoints
|
|
149
174
|
│ └── services/ # Business logic
|
|
150
|
-
├──
|
|
151
|
-
│
|
|
152
|
-
└──
|
|
175
|
+
├── conn-config/
|
|
176
|
+
│ ├── config.json # Service & wrapper configuration
|
|
177
|
+
│ └── operations.json # Operations specification
|
|
178
|
+
├── index.js # Main entry point (initializes wrapper)
|
|
179
|
+
└── package.json # Dependencies including @onlineapps/service-wrapper
|
|
153
180
|
```
|
|
154
181
|
|
|
155
182
|
## Testing
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# Architecture Decision: Service Wrapper vs Business Services
|
|
2
|
+
|
|
3
|
+
> **NOTE: This document describes the evolution of our thinking. For the final decision, see [FINAL_ARCHITECTURE.md](./FINAL_ARCHITECTURE.md)**
|
|
4
|
+
|
|
5
|
+
## Executive Summary
|
|
6
|
+
|
|
7
|
+
After critical analysis, we've determined that business services should remain as standard Express applications with Service Wrapper acting as a thin MQ-to-HTTP proxy layer.
|
|
8
|
+
|
|
9
|
+
## Business Service Requirements
|
|
10
|
+
|
|
11
|
+
### MUST Have:
|
|
12
|
+
1. **Express HTTP Server** - Full REST API capability
|
|
13
|
+
2. **Own Database Connections** - Direct ORM/query access
|
|
14
|
+
3. **Own Dependencies** - Complete node_modules
|
|
15
|
+
4. **Standalone Operation** - Must run without wrapper
|
|
16
|
+
5. **Standard Testing** - curl/Postman testable
|
|
17
|
+
|
|
18
|
+
### Service Structure:
|
|
19
|
+
```
|
|
20
|
+
/service-name/
|
|
21
|
+
/src/
|
|
22
|
+
app.js # Express application
|
|
23
|
+
/models/ # Database models
|
|
24
|
+
/controllers/ # HTTP controllers
|
|
25
|
+
/services/ # Business logic
|
|
26
|
+
/validators/ # Input validation
|
|
27
|
+
/conn-config/
|
|
28
|
+
operations.json # Operation definitions
|
|
29
|
+
config.json # Service configuration
|
|
30
|
+
package.json # All dependencies
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Operations Specification:
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"operations": {
|
|
37
|
+
"operation-name": {
|
|
38
|
+
"endpoint": "/api/operation",
|
|
39
|
+
"method": "POST",
|
|
40
|
+
"input": { "schema": "..." },
|
|
41
|
+
"output": { "schema": "..." }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Service Wrapper Responsibilities
|
|
48
|
+
|
|
49
|
+
### Core Functions:
|
|
50
|
+
1. **MQ Listener** - Consumes from RabbitMQ queues
|
|
51
|
+
2. **HTTP Proxy** - Forwards to service endpoints
|
|
52
|
+
3. **Service Registry** - Registers with discovery
|
|
53
|
+
4. **Cookbook Router** - Routes workflow steps
|
|
54
|
+
|
|
55
|
+
### What Wrapper Does NOT Do:
|
|
56
|
+
- ❌ Create HTTP server for service
|
|
57
|
+
- ❌ Handle business logic
|
|
58
|
+
- ❌ Manage database connections
|
|
59
|
+
- ❌ Validate business rules
|
|
60
|
+
- ❌ Generate responses
|
|
61
|
+
|
|
62
|
+
### Wrapper Architecture:
|
|
63
|
+
```javascript
|
|
64
|
+
// wrapper.js
|
|
65
|
+
const ServiceWrapper = require('@onlineapps/service-wrapper');
|
|
66
|
+
|
|
67
|
+
new ServiceWrapper({
|
|
68
|
+
serviceName: 'hello-service',
|
|
69
|
+
serviceUrl: 'http://localhost:3000',
|
|
70
|
+
mqConfig: { /* RabbitMQ settings */ },
|
|
71
|
+
mode: 'proxy' // Just forwards MQ→HTTP
|
|
72
|
+
}).start();
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Communication Flow
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
[Cookbook Message]
|
|
79
|
+
↓
|
|
80
|
+
[Service Wrapper]
|
|
81
|
+
├─ Reads operations.json
|
|
82
|
+
├─ Maps operation to endpoint
|
|
83
|
+
├─ Makes HTTP call
|
|
84
|
+
↓
|
|
85
|
+
[Business Service Express]
|
|
86
|
+
├─ Handles HTTP request
|
|
87
|
+
├─ Executes business logic
|
|
88
|
+
├─ Returns HTTP response
|
|
89
|
+
↓
|
|
90
|
+
[Service Wrapper]
|
|
91
|
+
├─ Transforms response
|
|
92
|
+
└─ Sends to next queue
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Why This Architecture?
|
|
96
|
+
|
|
97
|
+
### Separation of Concerns:
|
|
98
|
+
- **Business Service** = Business logic + API
|
|
99
|
+
- **Service Wrapper** = MQ communication only
|
|
100
|
+
|
|
101
|
+
### Benefits:
|
|
102
|
+
1. **Independence** - Services run standalone
|
|
103
|
+
2. **Simplicity** - No complex handler mapping
|
|
104
|
+
3. **Compatibility** - Works with existing services
|
|
105
|
+
4. **Testability** - Standard HTTP testing
|
|
106
|
+
5. **Flexibility** - Can swap wrapper implementations
|
|
107
|
+
|
|
108
|
+
### Drawbacks Considered:
|
|
109
|
+
- Extra HTTP hop (acceptable for clarity)
|
|
110
|
+
- Two processes (acceptable for isolation)
|
|
111
|
+
- More memory (acceptable for stability)
|
|
112
|
+
|
|
113
|
+
## Migration Path
|
|
114
|
+
|
|
115
|
+
### For New Services:
|
|
116
|
+
1. Build Express API normally
|
|
117
|
+
2. Add operations.json
|
|
118
|
+
3. Add wrapper.js for MQ
|
|
119
|
+
|
|
120
|
+
### For Existing Services:
|
|
121
|
+
1. Keep service unchanged
|
|
122
|
+
2. Add operations.json
|
|
123
|
+
3. Add wrapper.js for MQ
|
|
124
|
+
|
|
125
|
+
### No Breaking Changes Required!
|
|
126
|
+
|
|
127
|
+
## Decision Matrix
|
|
128
|
+
|
|
129
|
+
| Aspect | Handlers Approach | Express + Wrapper |
|
|
130
|
+
|--------|------------------|-------------------|
|
|
131
|
+
| Complexity | High | Low |
|
|
132
|
+
| Testing | Complex | Simple |
|
|
133
|
+
| Dependencies | Conflicting | Isolated |
|
|
134
|
+
| Database | Problematic | Natural |
|
|
135
|
+
| Debugging | Hard | Easy |
|
|
136
|
+
| **Winner** | ❌ | ✅ |
|
|
137
|
+
|
|
138
|
+
## Final Decision
|
|
139
|
+
|
|
140
|
+
**Business services remain as Express applications.**
|
|
141
|
+
**Service Wrapper acts as MQ-to-HTTP proxy only.**
|
|
142
|
+
|
|
143
|
+
This provides:
|
|
144
|
+
- Maximum compatibility
|
|
145
|
+
- Minimum complexity
|
|
146
|
+
- Clear separation
|
|
147
|
+
- Easy migration
|
|
148
|
+
|
|
149
|
+
## Implementation Guidelines
|
|
150
|
+
|
|
151
|
+
1. **Every service has:**
|
|
152
|
+
- Express app with REST endpoints
|
|
153
|
+
- operations.json describing operations
|
|
154
|
+
- Optional wrapper.js for MQ integration
|
|
155
|
+
|
|
156
|
+
2. **Service Wrapper:**
|
|
157
|
+
- Reads operations.json
|
|
158
|
+
- Listens to MQ
|
|
159
|
+
- Calls HTTP endpoints
|
|
160
|
+
- Returns responses to MQ
|
|
161
|
+
|
|
162
|
+
3. **No direct handler execution**
|
|
163
|
+
- Always through HTTP
|
|
164
|
+
- Clear contract via operations.json
|
|
165
|
+
- Standard REST patterns
|
|
166
|
+
|
|
167
|
+
## Examples
|
|
168
|
+
|
|
169
|
+
### Hello Service:
|
|
170
|
+
```javascript
|
|
171
|
+
// app.js - Standard Express
|
|
172
|
+
app.post('/api/good-day', (req, res) => {
|
|
173
|
+
res.json({ message: `Good day, ${req.body.name}!` });
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// operations.json - Contract
|
|
177
|
+
{
|
|
178
|
+
"operations": {
|
|
179
|
+
"good-day": {
|
|
180
|
+
"endpoint": "/api/good-day",
|
|
181
|
+
"method": "POST"
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// wrapper.js - MQ Bridge
|
|
187
|
+
new ServiceWrapper({
|
|
188
|
+
serviceUrl: 'http://localhost:33199'
|
|
189
|
+
}).start();
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Invoicing Service:
|
|
193
|
+
- Keeps all controllers, models, validators
|
|
194
|
+
- Adds operations.json
|
|
195
|
+
- Adds wrapper.js
|
|
196
|
+
- NO other changes needed
|
|
197
|
+
|
|
198
|
+
## Conclusion
|
|
199
|
+
|
|
200
|
+
The architecture prioritizes **simplicity and compatibility** over theoretical purity. Services remain standard Express apps, making them easy to develop, test, and maintain. Service Wrapper provides the MQ integration layer without disrupting the service internals.
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# Service Wrapper - Final Architecture Decision
|
|
2
|
+
|
|
3
|
+
## Executive Summary
|
|
4
|
+
|
|
5
|
+
Service Wrapper is a **collection of connectors** that provides all infrastructure components necessary for business services to function within the OA Drive system. It operates as a **single process architecture** where wrapper components run embedded within the service process.
|
|
6
|
+
|
|
7
|
+
## Core Principles
|
|
8
|
+
|
|
9
|
+
1. **Component Collection** - Service Wrapper is NOT a framework but a set of reusable connector components
|
|
10
|
+
2. **Single Process** - All components run in the same process as the business service
|
|
11
|
+
3. **Express + HTTP** - Business services remain standard Express applications
|
|
12
|
+
4. **MQ-to-HTTP Proxy** - Wrapper listens on RabbitMQ and makes local HTTP calls
|
|
13
|
+
5. **Zero Infrastructure in Services** - Services contain ONLY business logic
|
|
14
|
+
|
|
15
|
+
## Architecture Decision
|
|
16
|
+
|
|
17
|
+
### Why HTTP Pattern Over Handler Pattern
|
|
18
|
+
|
|
19
|
+
Despite handler pattern being **3.4x faster** (2.1ms vs 7.1ms) and using **67% less memory** (60MB vs 100MB), we chose the HTTP pattern because:
|
|
20
|
+
|
|
21
|
+
#### Handler Pattern Fatal Issues ❌
|
|
22
|
+
- **Node modules conflicts** - Service needs mongoose 5.x, wrapper needs 6.x = CONFLICT
|
|
23
|
+
- **Database connections broken** - Can't maintain connection pools
|
|
24
|
+
- **Third-party integration failures** - AWS SDK version conflicts
|
|
25
|
+
- **Testing becomes impossible** - Can't test service independently
|
|
26
|
+
|
|
27
|
+
#### HTTP Pattern Benefits ✅
|
|
28
|
+
- **100% compatibility** - All existing services work unchanged
|
|
29
|
+
- **Standard patterns** - All Express tooling works
|
|
30
|
+
- **Full functionality** - Databases, third-party services all work
|
|
31
|
+
- **Simple testing** - Service can run standalone
|
|
32
|
+
- **Acceptable overhead** - 5ms per request is negligible
|
|
33
|
+
|
|
34
|
+
### Verdict
|
|
35
|
+
For typical service with 100 req/s:
|
|
36
|
+
- Performance difference: 500ms spread across 100 requests = **5ms per request**
|
|
37
|
+
- **5ms overhead is acceptable price for working solution!**
|
|
38
|
+
|
|
39
|
+
## Implementation Architecture
|
|
40
|
+
|
|
41
|
+
### Service Structure
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
hello-service/
|
|
45
|
+
├── src/
|
|
46
|
+
│ ├── app.js # Express app - business logic only
|
|
47
|
+
│ ├── routes/ # Business endpoints
|
|
48
|
+
│ └── handlers/ # Business logic
|
|
49
|
+
├── conn-config/ # Wrapper configuration
|
|
50
|
+
│ ├── config.json # Service & wrapper config
|
|
51
|
+
│ └── operations.json # Operation to endpoint mapping
|
|
52
|
+
├── index.js # Main entry point (initializes wrapper)
|
|
53
|
+
├── package.json # Dependencies including @onlineapps/service-wrapper
|
|
54
|
+
└── .env # Environment variables
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Runtime Flow
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
// index.js - Service entry point
|
|
61
|
+
const express = require('express');
|
|
62
|
+
const { ServiceWrapper } = require('@onlineapps/service-wrapper');
|
|
63
|
+
const app = require('./src/app');
|
|
64
|
+
|
|
65
|
+
async function start() {
|
|
66
|
+
// 1. Start Express server
|
|
67
|
+
const server = app.listen(PORT);
|
|
68
|
+
|
|
69
|
+
// 2. Initialize wrapper components
|
|
70
|
+
const wrapper = new ServiceWrapper({
|
|
71
|
+
app,
|
|
72
|
+
server,
|
|
73
|
+
config: require('./conn-config/config.json'),
|
|
74
|
+
operations: require('./conn-config/operations.json')
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
await wrapper.initialize();
|
|
78
|
+
// Service now has all infrastructure components!
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Message Processing
|
|
83
|
+
|
|
84
|
+
#### HTTP Request Flow
|
|
85
|
+
```
|
|
86
|
+
Client → HTTP → Express Router → Handler → Response
|
|
87
|
+
↓
|
|
88
|
+
MonitoringConnector (metrics)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### MQ Message Flow
|
|
92
|
+
```
|
|
93
|
+
RabbitMQ → MQConnector → Parse operations.json → HTTP localhost:3000/api/endpoint
|
|
94
|
+
↓
|
|
95
|
+
Express Router → Handler
|
|
96
|
+
↓
|
|
97
|
+
Response → MQ
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Component Architecture
|
|
101
|
+
|
|
102
|
+
### Service Wrapper Components
|
|
103
|
+
|
|
104
|
+
1. **MQConnector** - RabbitMQ integration
|
|
105
|
+
- Listens on `workflow.init` queue
|
|
106
|
+
- Listens on `{service-name}.workflow` queue
|
|
107
|
+
- Routes messages based on operations.json
|
|
108
|
+
|
|
109
|
+
2. **MonitoringConnector** - Metrics collection
|
|
110
|
+
- Request tracking
|
|
111
|
+
- Performance metrics
|
|
112
|
+
- Error rates
|
|
113
|
+
|
|
114
|
+
3. **HealthConnector** - Health checks
|
|
115
|
+
- Provides `/health` endpoint
|
|
116
|
+
- Aggregates component status
|
|
117
|
+
- Custom health check support
|
|
118
|
+
|
|
119
|
+
4. **RegistryConnector** - Service discovery
|
|
120
|
+
- Registers service on startup
|
|
121
|
+
- Sends heartbeat
|
|
122
|
+
- Updates capabilities
|
|
123
|
+
|
|
124
|
+
## Operations Schema
|
|
125
|
+
|
|
126
|
+
Replaces OpenAPI with simpler format optimized for workflow processing:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"operations": {
|
|
131
|
+
"operation-name": {
|
|
132
|
+
"description": "Human-readable description",
|
|
133
|
+
"endpoint": "/api/operation-name",
|
|
134
|
+
"method": "POST",
|
|
135
|
+
"input": {
|
|
136
|
+
"field1": { "type": "string", "required": true }
|
|
137
|
+
},
|
|
138
|
+
"output": {
|
|
139
|
+
"result": { "type": "string" }
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Benefits of This Architecture
|
|
147
|
+
|
|
148
|
+
### For Development
|
|
149
|
+
- **Zero infrastructure code** in services
|
|
150
|
+
- **Standard Express patterns** work
|
|
151
|
+
- **Simple debugging** - one process, one log stream
|
|
152
|
+
- **Easy testing** - service runs standalone
|
|
153
|
+
|
|
154
|
+
### For Operations
|
|
155
|
+
- **Simple deployment** - one process per service
|
|
156
|
+
- **Central management** - update wrapper version for all
|
|
157
|
+
- **Graceful shutdown** - wrapper handles cleanup
|
|
158
|
+
- **No message loss** - RabbitMQ persistent queues
|
|
159
|
+
|
|
160
|
+
### For Performance
|
|
161
|
+
- **5ms overhead** - acceptable for real-world use
|
|
162
|
+
- **Efficient resource usage** - shared memory in single process
|
|
163
|
+
- **Connection pooling** - wrapper manages MQ connections
|
|
164
|
+
- **Horizontal scaling** - just add more service instances
|
|
165
|
+
|
|
166
|
+
## What Services DON'T Handle
|
|
167
|
+
|
|
168
|
+
- ❌ RabbitMQ connection management
|
|
169
|
+
- ❌ Queue subscription logic
|
|
170
|
+
- ❌ Message parsing and validation
|
|
171
|
+
- ❌ Service discovery registration
|
|
172
|
+
- ❌ Health check implementation
|
|
173
|
+
- ❌ Monitoring middleware
|
|
174
|
+
- ❌ Retry and error handling
|
|
175
|
+
|
|
176
|
+
**All handled by Service Wrapper components!**
|
|
177
|
+
|
|
178
|
+
## Migration Strategy
|
|
179
|
+
|
|
180
|
+
### For New Services
|
|
181
|
+
1. Create Express app with business logic
|
|
182
|
+
2. Add `conn-config/operations.json`
|
|
183
|
+
3. Add Service Wrapper dependency
|
|
184
|
+
4. Create `index.js` entry point
|
|
185
|
+
5. Deploy
|
|
186
|
+
|
|
187
|
+
### For Existing Services
|
|
188
|
+
1. Keep all existing code unchanged
|
|
189
|
+
2. Add configuration files
|
|
190
|
+
3. Wrap with Service Wrapper
|
|
191
|
+
4. Remove infrastructure code
|
|
192
|
+
5. Deploy - no breaking changes!
|
|
193
|
+
|
|
194
|
+
## Configuration
|
|
195
|
+
|
|
196
|
+
### Service Configuration (conn-config/config.json)
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"service": {
|
|
200
|
+
"name": "hello-service",
|
|
201
|
+
"version": "1.0.0",
|
|
202
|
+
"port": 3000
|
|
203
|
+
},
|
|
204
|
+
"wrapper": {
|
|
205
|
+
"mq": {
|
|
206
|
+
"url": "${RABBITMQ_URL}",
|
|
207
|
+
"prefetch": 10
|
|
208
|
+
},
|
|
209
|
+
"monitoring": {
|
|
210
|
+
"enabled": true
|
|
211
|
+
},
|
|
212
|
+
"health": {
|
|
213
|
+
"endpoint": "/health"
|
|
214
|
+
},
|
|
215
|
+
"registry": {
|
|
216
|
+
"url": "${REGISTRY_URL}"
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Testing Strategy
|
|
223
|
+
|
|
224
|
+
### Unit Tests (without wrapper)
|
|
225
|
+
```javascript
|
|
226
|
+
const app = require('./src/app');
|
|
227
|
+
const request = require('supertest');
|
|
228
|
+
|
|
229
|
+
test('business logic', async () => {
|
|
230
|
+
const res = await request(app).post('/api/operation');
|
|
231
|
+
expect(res.status).toBe(200);
|
|
232
|
+
});
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Integration Tests (with wrapper)
|
|
236
|
+
```javascript
|
|
237
|
+
const { start } = require('./index');
|
|
238
|
+
|
|
239
|
+
beforeAll(async () => {
|
|
240
|
+
await start();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test('full service', async () => {
|
|
244
|
+
// Test with all infrastructure
|
|
245
|
+
});
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Performance Characteristics
|
|
249
|
+
|
|
250
|
+
| Metric | Value | Acceptable? |
|
|
251
|
+
|--------|-------|-------------|
|
|
252
|
+
| Added latency | 5ms per request | ✅ Yes |
|
|
253
|
+
| Memory overhead | 40MB per service | ✅ Yes |
|
|
254
|
+
| CPU overhead | 4% per 1000 req/s | ✅ Yes |
|
|
255
|
+
| Startup time | +2 seconds | ✅ Yes |
|
|
256
|
+
|
|
257
|
+
## Conclusion
|
|
258
|
+
|
|
259
|
+
This architecture provides the **optimal balance** between:
|
|
260
|
+
- **Simplicity** - Single process, standard patterns
|
|
261
|
+
- **Compatibility** - Works with all existing services
|
|
262
|
+
- **Performance** - Acceptable overhead for massive benefits
|
|
263
|
+
- **Maintainability** - Central management, no duplication
|
|
264
|
+
|
|
265
|
+
The 5ms latency overhead is a **small price** for:
|
|
266
|
+
- 100% compatibility
|
|
267
|
+
- Zero infrastructure code in services
|
|
268
|
+
- Central management of all components
|
|
269
|
+
- Full functionality including databases
|
|
270
|
+
|
|
271
|
+
**This is the final, production-ready architecture for Service Wrapper.**
|