@memberjunction/queue 2.32.1 → 2.33.0
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 +255 -0
- package/package.json +6 -6
package/README.md
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# MemberJunction Queue
|
|
2
|
+
|
|
3
|
+
A library for creating and managing server-side queues in MemberJunction applications. This package provides a framework for task queuing, background processing, and asynchronous job execution.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `@memberjunction/queue` package offers a flexible architecture for implementing persistent queues in MemberJunction applications. It enables:
|
|
8
|
+
|
|
9
|
+
- Creation of background processing queues
|
|
10
|
+
- Task prioritization and scheduling
|
|
11
|
+
- Persistent storage of queue items in the database
|
|
12
|
+
- Retrying failed tasks with configurable policies
|
|
13
|
+
- Distributed queue processing across multiple server instances
|
|
14
|
+
- Monitoring and management of queue status
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @memberjunction/queue
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Dependencies
|
|
23
|
+
|
|
24
|
+
This package relies on the following MemberJunction packages:
|
|
25
|
+
- `@memberjunction/core` - Core functionality
|
|
26
|
+
- `@memberjunction/global` - Global utilities
|
|
27
|
+
- `@memberjunction/core-entities` - Entity definitions
|
|
28
|
+
- `@memberjunction/ai` - AI functionality (for AI-related queues)
|
|
29
|
+
- `@memberjunction/aiengine` - AI Engine integration
|
|
30
|
+
|
|
31
|
+
## Key Components
|
|
32
|
+
|
|
33
|
+
### QueueBase
|
|
34
|
+
|
|
35
|
+
The `QueueBase` class is the foundation for all queue implementations, providing:
|
|
36
|
+
|
|
37
|
+
- Queue item registration and tracking
|
|
38
|
+
- Processing lifecycle management
|
|
39
|
+
- Error handling and retry logic
|
|
40
|
+
- Status reporting and logging
|
|
41
|
+
|
|
42
|
+
### QueueManager
|
|
43
|
+
|
|
44
|
+
The `QueueManager` class manages multiple queues in an application:
|
|
45
|
+
|
|
46
|
+
- Registers and initializes queues
|
|
47
|
+
- Schedules queue processing
|
|
48
|
+
- Provides centralized queue access
|
|
49
|
+
- Supports prioritization across queues
|
|
50
|
+
|
|
51
|
+
### TaskBase
|
|
52
|
+
|
|
53
|
+
The `TaskBase` class is the parent class for all queue tasks, with:
|
|
54
|
+
|
|
55
|
+
- Task metadata and parameters
|
|
56
|
+
- Execution status tracking
|
|
57
|
+
- Retry information
|
|
58
|
+
- Result storage
|
|
59
|
+
|
|
60
|
+
### Specialized Queue Implementations
|
|
61
|
+
|
|
62
|
+
- `AIModelInferenceQueue`: Manages AI model inference requests
|
|
63
|
+
- `EntityProcessingQueue`: Processes entity-related tasks
|
|
64
|
+
- `NotificationQueue`: Handles notification delivery
|
|
65
|
+
- `GenericQueue`: Multi-purpose queue for general tasks
|
|
66
|
+
|
|
67
|
+
## Usage
|
|
68
|
+
|
|
69
|
+
### Basic Queue Usage
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import {
|
|
73
|
+
QueueManager,
|
|
74
|
+
QueueBase,
|
|
75
|
+
TaskBase,
|
|
76
|
+
TaskStatus
|
|
77
|
+
} from '@memberjunction/queue';
|
|
78
|
+
|
|
79
|
+
// Initialize the queue manager (typically done at application startup)
|
|
80
|
+
const queueManager = QueueManager.getInstance();
|
|
81
|
+
|
|
82
|
+
// Define a simple task
|
|
83
|
+
class EmailTask extends TaskBase {
|
|
84
|
+
recipient: string;
|
|
85
|
+
subject: string;
|
|
86
|
+
body: string;
|
|
87
|
+
|
|
88
|
+
constructor(recipient: string, subject: string, body: string) {
|
|
89
|
+
super();
|
|
90
|
+
this.recipient = recipient;
|
|
91
|
+
this.subject = subject;
|
|
92
|
+
this.body = body;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Implement a custom queue
|
|
97
|
+
class EmailQueue extends QueueBase {
|
|
98
|
+
constructor() {
|
|
99
|
+
super('EmailQueue', 'Handles email sending tasks');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Implement the processing logic
|
|
103
|
+
protected async processTask(task: EmailTask): Promise<boolean> {
|
|
104
|
+
try {
|
|
105
|
+
// Actual implementation would use an email service
|
|
106
|
+
console.log(`Sending email to ${task.recipient}`);
|
|
107
|
+
console.log(`Subject: ${task.subject}`);
|
|
108
|
+
console.log(`Body: ${task.body}`);
|
|
109
|
+
|
|
110
|
+
// Return true if processing succeeded
|
|
111
|
+
return true;
|
|
112
|
+
} catch (error) {
|
|
113
|
+
console.error('Error sending email:', error);
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Register the queue
|
|
120
|
+
queueManager.registerQueue(new EmailQueue());
|
|
121
|
+
|
|
122
|
+
// Start queue processing
|
|
123
|
+
queueManager.startProcessing();
|
|
124
|
+
|
|
125
|
+
// Add a task to the queue
|
|
126
|
+
async function sendEmailLater(recipient: string, subject: string, body: string) {
|
|
127
|
+
const task = new EmailTask(recipient, subject, body);
|
|
128
|
+
await queueManager.getQueue('EmailQueue').addTask(task);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Usage
|
|
132
|
+
sendEmailLater(
|
|
133
|
+
'user@example.com',
|
|
134
|
+
'Welcome to MemberJunction',
|
|
135
|
+
'Thank you for registering with MemberJunction!'
|
|
136
|
+
);
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Creating a Custom Queue Implementation
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { QueueBase, TaskBase, LoggingLevel } from '@memberjunction/queue';
|
|
143
|
+
import { BaseEntity } from '@memberjunction/core';
|
|
144
|
+
|
|
145
|
+
// Define a custom task type
|
|
146
|
+
class DataSyncTask extends TaskBase {
|
|
147
|
+
entityName: string;
|
|
148
|
+
recordId: number;
|
|
149
|
+
sourceSystem: string;
|
|
150
|
+
|
|
151
|
+
constructor(entityName: string, recordId: number, sourceSystem: string) {
|
|
152
|
+
super();
|
|
153
|
+
this.entityName = entityName;
|
|
154
|
+
this.recordId = recordId;
|
|
155
|
+
this.sourceSystem = sourceSystem;
|
|
156
|
+
|
|
157
|
+
// Set task options
|
|
158
|
+
this.maxRetries = 3; // Allow 3 retries
|
|
159
|
+
this.priority = 2; // Higher priority (lower number = higher priority)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Implement the queue
|
|
164
|
+
class DataSynchronizationQueue extends QueueBase {
|
|
165
|
+
constructor() {
|
|
166
|
+
super('DataSyncQueue', 'Synchronizes data with external systems');
|
|
167
|
+
|
|
168
|
+
// Configure queue settings
|
|
169
|
+
this.maxConcurrentTasks = 5;
|
|
170
|
+
this.processingInterval = 60000; // Process every minute
|
|
171
|
+
this.loggingLevel = LoggingLevel.Detailed;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
protected async processTask(task: DataSyncTask): Promise<boolean> {
|
|
175
|
+
// Validate task
|
|
176
|
+
if (!task.entityName || !task.recordId || !task.sourceSystem) {
|
|
177
|
+
this.logError(`Invalid task parameters: ${JSON.stringify(task)}`);
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
// Get entity metadata and create instance
|
|
183
|
+
const md = BaseEntity.getEntityMetadata(task.entityName);
|
|
184
|
+
const entity = BaseEntity.createByEntityName(task.entityName);
|
|
185
|
+
|
|
186
|
+
// Load the entity
|
|
187
|
+
const loaded = await entity.load(task.recordId);
|
|
188
|
+
if (!loaded) {
|
|
189
|
+
this.logWarning(`Entity ${task.entityName} with ID ${task.recordId} not found`);
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Perform synchronization (implementation details)
|
|
194
|
+
this.logInfo(`Synchronizing ${task.entityName} #${task.recordId} with ${task.sourceSystem}`);
|
|
195
|
+
|
|
196
|
+
// In a real implementation, you would call external APIs here
|
|
197
|
+
|
|
198
|
+
// Update entity with synchronized data
|
|
199
|
+
await entity.save();
|
|
200
|
+
|
|
201
|
+
return true;
|
|
202
|
+
} catch (error) {
|
|
203
|
+
this.logError(`Error synchronizing data: ${error}`);
|
|
204
|
+
|
|
205
|
+
// If this is a retriable error, return false to trigger retry
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Queue Manager Configuration
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import { QueueManager, LoggingLevel } from '@memberjunction/queue';
|
|
216
|
+
|
|
217
|
+
// Get the singleton instance
|
|
218
|
+
const queueManager = QueueManager.getInstance();
|
|
219
|
+
|
|
220
|
+
// Configure queue manager
|
|
221
|
+
queueManager.configure({
|
|
222
|
+
globalMaxConcurrentTasks: 20,
|
|
223
|
+
defaultLoggingLevel: LoggingLevel.Normal,
|
|
224
|
+
defaultProcessingInterval: 30000,
|
|
225
|
+
databaseCleanupInterval: 86400000, // Clean up completed tasks daily
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Register multiple queues
|
|
229
|
+
queueManager.registerQueue(new EmailQueue());
|
|
230
|
+
queueManager.registerQueue(new DataSynchronizationQueue());
|
|
231
|
+
queueManager.registerQueue(new NotificationQueue());
|
|
232
|
+
|
|
233
|
+
// Start processing on all queues
|
|
234
|
+
queueManager.startProcessing();
|
|
235
|
+
|
|
236
|
+
// Or start selectively
|
|
237
|
+
queueManager.startProcessing(['EmailQueue', 'NotificationQueue']);
|
|
238
|
+
|
|
239
|
+
// Stop processing when needed
|
|
240
|
+
queueManager.stopProcessing();
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Database Schema
|
|
244
|
+
|
|
245
|
+
This package relies on database tables to store queue and task information. The required tables are:
|
|
246
|
+
|
|
247
|
+
- `__mj.Queue` - Stores queue definitions
|
|
248
|
+
- `__mj.QueueTask` - Stores individual tasks
|
|
249
|
+
- `__mj.QueueTaskExecution` - Tracks task execution history
|
|
250
|
+
|
|
251
|
+
These tables should be automatically created during MemberJunction schema installation.
|
|
252
|
+
|
|
253
|
+
## License
|
|
254
|
+
|
|
255
|
+
ISC
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/queue",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.33.0",
|
|
4
4
|
"description": "MemberJunction: Queue Library for managing server side queues",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
"typescript": "^5.4.5"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@memberjunction/ai": "2.
|
|
23
|
-
"@memberjunction/aiengine": "2.
|
|
24
|
-
"@memberjunction/core": "2.
|
|
25
|
-
"@memberjunction/global": "2.
|
|
26
|
-
"@memberjunction/core-entities": "2.
|
|
22
|
+
"@memberjunction/ai": "2.33.0",
|
|
23
|
+
"@memberjunction/aiengine": "2.33.0",
|
|
24
|
+
"@memberjunction/core": "2.33.0",
|
|
25
|
+
"@memberjunction/global": "2.33.0",
|
|
26
|
+
"@memberjunction/core-entities": "2.33.0",
|
|
27
27
|
"@types/uuid": "^9.0.1",
|
|
28
28
|
"uuid": "^9.0.0"
|
|
29
29
|
}
|