@memberjunction/queue 2.43.0 → 2.45.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.
Files changed (2) hide show
  1. package/README.md +269 -187
  2. package/package.json +6 -6
package/README.md CHANGED
@@ -1,17 +1,17 @@
1
- # MemberJunction Queue
1
+ # @memberjunction/queue
2
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.
3
+ A flexible queue management system for MemberJunction applications that enables background task processing, job scheduling, and asynchronous execution with database persistence.
4
4
 
5
5
  ## Overview
6
6
 
7
- The `@memberjunction/queue` package offers a flexible architecture for implementing persistent queues in MemberJunction applications. It enables:
7
+ The `@memberjunction/queue` package provides a robust framework for implementing persistent queues in MemberJunction applications. It offers:
8
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
9
+ - Database-backed task persistence
10
+ - Automatic queue creation and management
11
+ - Concurrent task processing with configurable limits
12
+ - Heartbeat monitoring for process health
13
+ - Type-safe task definitions
14
+ - Extensible queue implementations
15
15
 
16
16
  ## Installation
17
17
 
@@ -21,234 +21,316 @@ npm install @memberjunction/queue
21
21
 
22
22
  ## Dependencies
23
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
24
+ This package requires the following MemberJunction packages:
25
+
26
+ - `@memberjunction/core` - Core functionality and entity management
27
+ - `@memberjunction/global` - Global utilities and class registration
28
+ - `@memberjunction/core-entities` - Entity type definitions
28
29
  - `@memberjunction/ai` - AI functionality (for AI-related queues)
29
30
  - `@memberjunction/aiengine` - AI Engine integration
30
31
 
31
- ## Key Components
32
+ Additional dependencies:
33
+ - `uuid` - For generating unique identifiers
32
34
 
33
- ### QueueBase
35
+ ## Core Components
34
36
 
35
- The `QueueBase` class is the foundation for all queue implementations, providing:
37
+ ### TaskBase
36
38
 
37
- - Queue item registration and tracking
38
- - Processing lifecycle management
39
- - Error handling and retry logic
40
- - Status reporting and logging
39
+ The `TaskBase` class represents an individual task in a queue:
41
40
 
42
- ### QueueManager
41
+ ```typescript
42
+ export class TaskBase {
43
+ constructor(
44
+ taskRecord: QueueTaskEntity,
45
+ data: any,
46
+ options: TaskOptions
47
+ )
48
+
49
+ // Properties
50
+ ID: string // Unique task identifier
51
+ Status: TaskStatus // Current task status
52
+ Data: any // Task payload data
53
+ Options: TaskOptions // Task configuration
54
+ TaskRecord: QueueTaskEntity // Database entity
55
+ }
56
+ ```
43
57
 
44
- The `QueueManager` class manages multiple queues in an application:
58
+ ### TaskStatus
45
59
 
46
- - Registers and initializes queues
47
- - Schedules queue processing
48
- - Provides centralized queue access
49
- - Supports prioritization across queues
60
+ Available task statuses:
50
61
 
51
- ### TaskBase
62
+ ```typescript
63
+ export const TaskStatus = {
64
+ Pending: 'Pending',
65
+ InProgress: 'InProgress',
66
+ Complete: 'Complete',
67
+ Failed: 'Failed',
68
+ Cancelled: 'Cancelled',
69
+ } as const;
70
+ ```
71
+
72
+ ### QueueBase
52
73
 
53
- The `TaskBase` class is the parent class for all queue tasks, with:
74
+ The abstract `QueueBase` class serves as the foundation for all queue implementations:
75
+
76
+ ```typescript
77
+ export abstract class QueueBase {
78
+ constructor(
79
+ QueueRecord: QueueEntity,
80
+ QueueTypeID: string,
81
+ ContextUser: UserInfo
82
+ )
83
+
84
+ // Public methods
85
+ AddTask(task: TaskBase): boolean
86
+ FindTask(ID: string): TaskBase
87
+
88
+ // Protected abstract method to implement
89
+ protected abstract ProcessTask(
90
+ task: TaskBase,
91
+ contextUser: UserInfo
92
+ ): Promise<TaskResult>
93
+ }
94
+ ```
54
95
 
55
- - Task metadata and parameters
56
- - Execution status tracking
57
- - Retry information
58
- - Result storage
96
+ ### QueueManager
59
97
 
60
- ### Specialized Queue Implementations
98
+ The `QueueManager` is a singleton that manages all active queues:
61
99
 
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
100
+ ```typescript
101
+ export class QueueManager {
102
+ // Singleton access
103
+ static get Instance(): QueueManager
104
+
105
+ // Static methods
106
+ static async Config(contextUser: UserInfo): Promise<void>
107
+ static async AddTask(
108
+ QueueType: string,
109
+ data: any,
110
+ options: any,
111
+ contextUser: UserInfo
112
+ ): Promise<TaskBase | undefined>
113
+
114
+ // Instance methods
115
+ async AddTask(
116
+ QueueTypeID: string,
117
+ data: any,
118
+ options: any,
119
+ contextUser: UserInfo
120
+ ): Promise<TaskBase | undefined>
121
+ }
122
+ ```
66
123
 
67
- ## Usage
124
+ ### TaskResult
68
125
 
69
- ### Basic Queue Usage
126
+ Structure returned by task processing:
70
127
 
71
128
  ```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
- }
129
+ export class TaskResult {
130
+ success: boolean // Whether task completed successfully
131
+ userMessage: string // User-friendly message
132
+ output: any // Task output data
133
+ exception: any // Exception details if failed
94
134
  }
135
+ ```
95
136
 
96
- // Implement a custom queue
97
- class EmailQueue extends QueueBase {
98
- constructor() {
99
- super('EmailQueue', 'Handles email sending tasks');
100
- }
137
+ ## Usage Examples
138
+
139
+ ### Basic Queue Implementation
101
140
 
102
- // Implement the processing logic
103
- protected async processTask(task: EmailTask): Promise<boolean> {
141
+ Create a custom queue by extending `QueueBase`:
142
+
143
+ ```typescript
144
+ import { QueueBase, TaskBase, TaskResult } from '@memberjunction/queue';
145
+ import { RegisterClass } from '@memberjunction/global';
146
+ import { UserInfo } from '@memberjunction/core';
147
+
148
+ // Register your queue with a specific queue type name
149
+ @RegisterClass(QueueBase, 'Email Notification')
150
+ export class EmailNotificationQueue extends QueueBase {
151
+ protected async ProcessTask(
152
+ task: TaskBase,
153
+ contextUser: UserInfo
154
+ ): Promise<TaskResult> {
104
155
  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}`);
156
+ // Extract task data
157
+ const { recipient, subject, body } = task.Data;
158
+
159
+ // Implement your email sending logic here
160
+ console.log(`Sending email to ${recipient}`);
161
+ console.log(`Subject: ${subject}`);
109
162
 
110
- // Return true if processing succeeded
111
- return true;
163
+ // Simulate email sending
164
+ await this.sendEmail(recipient, subject, body);
165
+
166
+ // Return success result
167
+ return {
168
+ success: true,
169
+ userMessage: 'Email sent successfully',
170
+ output: { sentAt: new Date() },
171
+ exception: null
172
+ };
112
173
  } catch (error) {
113
- console.error('Error sending email:', error);
114
- return false;
174
+ // Return failure result
175
+ return {
176
+ success: false,
177
+ userMessage: `Failed to send email: ${error.message}`,
178
+ output: null,
179
+ exception: error
180
+ };
115
181
  }
116
182
  }
183
+
184
+ private async sendEmail(to: string, subject: string, body: string) {
185
+ // Your email service integration here
186
+ }
117
187
  }
188
+ ```
118
189
 
119
- // Register the queue
120
- queueManager.registerQueue(new EmailQueue());
190
+ ### Adding Tasks to Queue
121
191
 
122
- // Start queue processing
123
- queueManager.startProcessing();
192
+ ```typescript
193
+ import { QueueManager } from '@memberjunction/queue';
194
+ import { UserInfo } from '@memberjunction/core';
195
+
196
+ // Initialize queue manager (typically done once at app startup)
197
+ await QueueManager.Config(contextUser);
198
+
199
+ // Add a task using queue type name
200
+ const task = await QueueManager.AddTask(
201
+ 'Email Notification', // Queue type name
202
+ { // Task data
203
+ recipient: 'user@example.com',
204
+ subject: 'Welcome to MemberJunction',
205
+ body: 'Thank you for joining!'
206
+ },
207
+ { // Task options
208
+ priority: 1
209
+ },
210
+ contextUser
211
+ );
124
212
 
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);
213
+ if (task) {
214
+ console.log(`Task created with ID: ${task.ID}`);
129
215
  }
130
-
131
- // Usage
132
- sendEmailLater(
133
- 'user@example.com',
134
- 'Welcome to MemberJunction',
135
- 'Thank you for registering with MemberJunction!'
136
- );
137
216
  ```
138
217
 
139
- ### Creating a Custom Queue Implementation
218
+ ### AI Action Queue Example
219
+
220
+ The package includes built-in queues for AI operations:
140
221
 
141
222
  ```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
- }
223
+ import { AIActionQueue, EntityAIActionQueue } from '@memberjunction/queue';
224
+
225
+ // These queues are automatically registered and available for use
226
+ // Add an AI action task
227
+ const aiTask = await QueueManager.AddTask(
228
+ 'AI Action',
229
+ {
230
+ actionName: 'GenerateText',
231
+ prompt: 'Write a product description',
232
+ parameters: { maxTokens: 100 }
233
+ },
234
+ {},
235
+ contextUser
236
+ );
162
237
 
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
- }
238
+ // Add an entity-specific AI action
239
+ const entityAITask = await QueueManager.AddTask(
240
+ 'Entity AI Action',
241
+ {
242
+ entityName: 'Products',
243
+ entityID: 123,
244
+ actionName: 'GenerateDescription'
245
+ },
246
+ {},
247
+ contextUser
248
+ );
210
249
  ```
211
250
 
212
- ### Queue Manager Configuration
251
+ ## Database Schema
213
252
 
214
- ```typescript
215
- import { QueueManager, LoggingLevel } from '@memberjunction/queue';
253
+ The queue system requires the following database tables:
216
254
 
217
- // Get the singleton instance
218
- const queueManager = QueueManager.getInstance();
255
+ ### Queue Types Table (`__mj.QueueType`)
256
+ Stores definitions of different queue types (e.g., "Email Notification", "AI Action")
219
257
 
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
- });
258
+ ### Queues Table (`__mj.Queue`)
259
+ Tracks active queue instances with process information:
260
+ - Queue type reference
261
+ - Process details (PID, platform, hostname)
262
+ - Heartbeat timestamp
263
+ - Network information
227
264
 
228
- // Register multiple queues
229
- queueManager.registerQueue(new EmailQueue());
230
- queueManager.registerQueue(new DataSynchronizationQueue());
231
- queueManager.registerQueue(new NotificationQueue());
265
+ ### Queue Tasks Table (`__mj.QueueTask`)
266
+ Stores individual tasks:
267
+ - Queue reference
268
+ - Task status
269
+ - Task data (JSON)
270
+ - Task options (JSON)
271
+ - Output and error information
232
272
 
233
- // Start processing on all queues
234
- queueManager.startProcessing();
273
+ ## Process Management
235
274
 
236
- // Or start selectively
237
- queueManager.startProcessing(['EmailQueue', 'NotificationQueue']);
275
+ The QueueManager automatically captures process information for monitoring:
276
+ - Process ID (PID)
277
+ - Platform and version
278
+ - Working directory
279
+ - Network interfaces
280
+ - Operating system details
281
+ - User information
282
+ - Heartbeat timestamps
238
283
 
239
- // Stop processing when needed
240
- queueManager.stopProcessing();
284
+ This information helps track queue health and enables failover scenarios.
285
+
286
+ ## Configuration
287
+
288
+ Queue behavior can be configured through the implementation:
289
+
290
+ ```typescript
291
+ export class CustomQueue extends QueueBase {
292
+ private _maxTasks = 5; // Maximum concurrent tasks
293
+ private _checkInterval = 500; // Check interval in milliseconds
294
+
295
+ // Override these values in your constructor
296
+ constructor(QueueRecord: QueueEntity, QueueTypeID: string, ContextUser: UserInfo) {
297
+ super(QueueRecord, QueueTypeID, ContextUser);
298
+ // Customize queue behavior
299
+ this._maxTasks = 10;
300
+ this._checkInterval = 1000;
301
+ }
302
+ }
241
303
  ```
242
304
 
243
- ## Database Schema
305
+ ## Best Practices
306
+
307
+ 1. **Task Data Structure**: Keep task data serializable as JSON
308
+ 2. **Error Handling**: Always return proper TaskResult with error details
309
+ 3. **Queue Registration**: Use `@RegisterClass` decorator for automatic registration
310
+ 4. **Idempotency**: Design tasks to be safely retryable
311
+ 5. **Resource Cleanup**: Clean up resources in finally blocks
312
+ 6. **Monitoring**: Check heartbeat timestamps for queue health
313
+
314
+ ## Integration with MemberJunction
244
315
 
245
- This package relies on database tables to store queue and task information. The required tables are:
316
+ The queue system integrates seamlessly with:
317
+ - **Entity System**: Use entities for task data and processing
318
+ - **User Context**: All operations respect user permissions
319
+ - **Global Registry**: Automatic queue discovery via class registration
320
+ - **AI Engine**: Built-in support for AI task processing
246
321
 
247
- - `__mj.Queue` - Stores queue definitions
248
- - `__mj.QueueTask` - Stores individual tasks
249
- - `__mj.QueueTaskExecution` - Tracks task execution history
322
+ ## Build & Development
250
323
 
251
- These tables should be automatically created during MemberJunction schema installation.
324
+ ```bash
325
+ # Build the package
326
+ npm run build
327
+
328
+ # Development mode with auto-reload
329
+ npm run start
330
+
331
+ # TypeScript compilation only
332
+ npm run build
333
+ ```
252
334
 
253
335
  ## License
254
336
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/queue",
3
- "version": "2.43.0",
3
+ "version": "2.45.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.43.0",
23
- "@memberjunction/aiengine": "2.43.0",
24
- "@memberjunction/core": "2.43.0",
25
- "@memberjunction/global": "2.43.0",
26
- "@memberjunction/core-entities": "2.43.0",
22
+ "@memberjunction/ai": "2.45.0",
23
+ "@memberjunction/aiengine": "2.45.0",
24
+ "@memberjunction/core": "2.45.0",
25
+ "@memberjunction/global": "2.45.0",
26
+ "@memberjunction/core-entities": "2.45.0",
27
27
  "@types/uuid": "^9.0.1",
28
28
  "uuid": "^9.0.0"
29
29
  }