s3db.js 8.2.0 → 9.2.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/PLUGINS.md +507 -0
- package/README.md +14 -10
- package/dist/s3db-cli.js +54741 -0
- package/dist/s3db.cjs.js +2125 -5702
- package/dist/s3db.cjs.js.map +1 -0
- package/dist/s3db.es.js +2114 -5697
- package/dist/s3db.es.js.map +1 -0
- package/package.json +45 -29
- package/src/cli/index.js +426 -0
- package/src/client.class.js +8 -33
- package/src/concerns/advanced-metadata-encoding.js +440 -0
- package/src/concerns/calculator.js +36 -0
- package/src/concerns/metadata-encoding.js +244 -0
- package/src/concerns/optimized-encoding.js +130 -0
- package/src/plugins/backup.plugin.js +1018 -0
- package/src/plugins/cache/memory-cache.class.js +112 -3
- package/src/plugins/index.js +3 -0
- package/src/plugins/scheduler.plugin.js +834 -0
- package/src/plugins/state-machine.plugin.js +543 -0
- package/dist/s3db.cjs.min.js +0 -1
- package/dist/s3db.es.min.js +0 -1
- package/dist/s3db.iife.js +0 -15738
- package/dist/s3db.iife.min.js +0 -1
package/PLUGINS.md
CHANGED
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
- [📊 Metrics Plugin](#-metrics-plugin)
|
|
19
19
|
- [🔄 Replicator Plugin](#-replicator-plugin)
|
|
20
20
|
- [📬 Queue Consumer Plugin](#-queue-consumer-plugin)
|
|
21
|
+
- [🤖 State Machine Plugin](#-state-machine-plugin)
|
|
22
|
+
- [💾 Backup Plugin](#-backup-plugin)
|
|
23
|
+
- [⏰ Scheduler Plugin](#-scheduler-plugin)
|
|
21
24
|
- [🔧 Plugin Development](#-plugin-development)
|
|
22
25
|
- [💡 Plugin Combinations](#-plugin-combinations)
|
|
23
26
|
- [🎯 Best Practices](#-best-practices)
|
|
@@ -4143,6 +4146,501 @@ const s3db = new S3db({
|
|
|
4143
4146
|
|
|
4144
4147
|
---
|
|
4145
4148
|
|
|
4149
|
+
## 🤖 State Machine Plugin
|
|
4150
|
+
|
|
4151
|
+
Finite state machine capabilities for managing complex workflows and business processes with well-defined states and transitions.
|
|
4152
|
+
|
|
4153
|
+
### ⚡ Quick Start
|
|
4154
|
+
|
|
4155
|
+
```javascript
|
|
4156
|
+
import { S3db, StateMachinePlugin } from 's3db.js';
|
|
4157
|
+
|
|
4158
|
+
const s3db = new S3db({
|
|
4159
|
+
connectionString: "s3://ACCESS_KEY:SECRET_KEY@BUCKET_NAME/databases/myapp",
|
|
4160
|
+
plugins: [
|
|
4161
|
+
new StateMachinePlugin({
|
|
4162
|
+
stateMachines: {
|
|
4163
|
+
order_processing: {
|
|
4164
|
+
initialState: 'pending',
|
|
4165
|
+
states: {
|
|
4166
|
+
pending: {
|
|
4167
|
+
on: { CONFIRM: 'confirmed', CANCEL: 'cancelled' }
|
|
4168
|
+
},
|
|
4169
|
+
confirmed: {
|
|
4170
|
+
on: { PREPARE: 'preparing', CANCEL: 'cancelled' },
|
|
4171
|
+
entry: 'onConfirmed'
|
|
4172
|
+
},
|
|
4173
|
+
preparing: {
|
|
4174
|
+
on: { SHIP: 'shipped', CANCEL: 'cancelled' },
|
|
4175
|
+
guards: { SHIP: 'canShip' }
|
|
4176
|
+
},
|
|
4177
|
+
shipped: {
|
|
4178
|
+
on: { DELIVER: 'delivered', RETURN: 'returned' }
|
|
4179
|
+
},
|
|
4180
|
+
delivered: { type: 'final' },
|
|
4181
|
+
cancelled: { type: 'final' },
|
|
4182
|
+
returned: { type: 'final' }
|
|
4183
|
+
}
|
|
4184
|
+
}
|
|
4185
|
+
},
|
|
4186
|
+
actions: {
|
|
4187
|
+
onConfirmed: async (context, event, machine) => {
|
|
4188
|
+
console.log(`Order ${context.id} confirmed!`);
|
|
4189
|
+
return { action: 'confirmed', timestamp: new Date() };
|
|
4190
|
+
}
|
|
4191
|
+
},
|
|
4192
|
+
guards: {
|
|
4193
|
+
canShip: async (context, event, machine) => {
|
|
4194
|
+
const inventory = await machine.database.resource('inventory').get(context.productId);
|
|
4195
|
+
return inventory && inventory.quantity >= context.quantity;
|
|
4196
|
+
}
|
|
4197
|
+
}
|
|
4198
|
+
})
|
|
4199
|
+
]
|
|
4200
|
+
});
|
|
4201
|
+
|
|
4202
|
+
await s3db.connect();
|
|
4203
|
+
|
|
4204
|
+
// Initialize entity with state machine
|
|
4205
|
+
await s3db.plugins.stateMachine.initializeEntity('order_processing', 'order123');
|
|
4206
|
+
|
|
4207
|
+
// Send events to trigger transitions
|
|
4208
|
+
await s3db.plugins.stateMachine.send('order_processing', 'order123', 'CONFIRM', {
|
|
4209
|
+
id: 'order123',
|
|
4210
|
+
productId: 'prod1',
|
|
4211
|
+
quantity: 2
|
|
4212
|
+
});
|
|
4213
|
+
|
|
4214
|
+
// Get current state
|
|
4215
|
+
const state = await s3db.plugins.stateMachine.getState('order_processing', 'order123');
|
|
4216
|
+
console.log('Current state:', state); // 'confirmed'
|
|
4217
|
+
```
|
|
4218
|
+
|
|
4219
|
+
### ⚙️ Configuration Parameters
|
|
4220
|
+
|
|
4221
|
+
| Parameter | Type | Default | Description |
|
|
4222
|
+
|-----------|------|---------|-------------|
|
|
4223
|
+
| `stateMachines` | object | `{}` | State machine definitions |
|
|
4224
|
+
| `actions` | object | `{}` | Action functions for state entry/exit |
|
|
4225
|
+
| `guards` | object | `{}` | Guard functions for transition validation |
|
|
4226
|
+
| `persistTransitions` | boolean | `true` | Store transition history in database |
|
|
4227
|
+
| `transitionLogResource` | string | `'transitions'` | Resource name for transition log |
|
|
4228
|
+
| `stateResource` | string | `'entity_states'` | Resource name for current states |
|
|
4229
|
+
| `verbose` | boolean | `false` | Enable detailed logging |
|
|
4230
|
+
|
|
4231
|
+
### State Machine Definition Structure
|
|
4232
|
+
|
|
4233
|
+
```javascript
|
|
4234
|
+
stateMachines: {
|
|
4235
|
+
machine_name: {
|
|
4236
|
+
initialState: 'start_state',
|
|
4237
|
+
states: {
|
|
4238
|
+
state_name: {
|
|
4239
|
+
on: { EVENT_NAME: 'target_state' }, // Transitions
|
|
4240
|
+
entry: 'action_name', // Action on state entry
|
|
4241
|
+
exit: 'action_name', // Action on state exit
|
|
4242
|
+
guards: { EVENT_NAME: 'guard_name' }, // Transition guards
|
|
4243
|
+
meta: { custom: 'metadata' }, // Additional metadata
|
|
4244
|
+
type: 'final' // Mark as final state
|
|
4245
|
+
}
|
|
4246
|
+
}
|
|
4247
|
+
}
|
|
4248
|
+
}
|
|
4249
|
+
```
|
|
4250
|
+
|
|
4251
|
+
### API Methods
|
|
4252
|
+
|
|
4253
|
+
```javascript
|
|
4254
|
+
// Entity management
|
|
4255
|
+
await stateMachine.initializeEntity(machineId, entityId, context);
|
|
4256
|
+
const state = await stateMachine.getState(machineId, entityId);
|
|
4257
|
+
const result = await stateMachine.send(machineId, entityId, event, context);
|
|
4258
|
+
|
|
4259
|
+
// State information
|
|
4260
|
+
const events = stateMachine.getValidEvents(machineId, entityId);
|
|
4261
|
+
const definition = stateMachine.getMachineDefinition(machineId);
|
|
4262
|
+
const machines = stateMachine.getMachines();
|
|
4263
|
+
|
|
4264
|
+
// History and visualization
|
|
4265
|
+
const history = await stateMachine.getTransitionHistory(machineId, entityId);
|
|
4266
|
+
const dot = stateMachine.visualize(machineId); // Graphviz DOT format
|
|
4267
|
+
```
|
|
4268
|
+
|
|
4269
|
+
### Events
|
|
4270
|
+
|
|
4271
|
+
```javascript
|
|
4272
|
+
stateMachine.on('initialized', ({ machines }) => {
|
|
4273
|
+
console.log('Initialized machines:', machines);
|
|
4274
|
+
});
|
|
4275
|
+
|
|
4276
|
+
stateMachine.on('transition', ({ machineId, entityId, from, to, event, context }) => {
|
|
4277
|
+
console.log(`${entityId}: ${from} → ${to} via ${event}`);
|
|
4278
|
+
});
|
|
4279
|
+
|
|
4280
|
+
stateMachine.on('action_error', ({ actionName, error, machineId, entityId }) => {
|
|
4281
|
+
console.error(`Action ${actionName} failed:`, error);
|
|
4282
|
+
});
|
|
4283
|
+
```
|
|
4284
|
+
|
|
4285
|
+
---
|
|
4286
|
+
|
|
4287
|
+
## 💾 Backup Plugin
|
|
4288
|
+
|
|
4289
|
+
Comprehensive database backup and restore capabilities with support for multiple destinations, compression, encryption, and retention policies.
|
|
4290
|
+
|
|
4291
|
+
### ⚡ Quick Start
|
|
4292
|
+
|
|
4293
|
+
```javascript
|
|
4294
|
+
import { S3db, BackupPlugin } from 's3db.js';
|
|
4295
|
+
|
|
4296
|
+
const s3db = new S3db({
|
|
4297
|
+
connectionString: "s3://ACCESS_KEY:SECRET_KEY@BUCKET_NAME/databases/myapp",
|
|
4298
|
+
plugins: [
|
|
4299
|
+
new BackupPlugin({
|
|
4300
|
+
destinations: [
|
|
4301
|
+
{
|
|
4302
|
+
type: 'filesystem',
|
|
4303
|
+
path: './backups/{date}/',
|
|
4304
|
+
compression: 'gzip'
|
|
4305
|
+
}
|
|
4306
|
+
],
|
|
4307
|
+
retention: {
|
|
4308
|
+
daily: 7,
|
|
4309
|
+
weekly: 4,
|
|
4310
|
+
monthly: 12
|
|
4311
|
+
},
|
|
4312
|
+
onBackupComplete: (type, stats) => {
|
|
4313
|
+
console.log(`${type} backup completed:`, {
|
|
4314
|
+
size: `${Math.round(stats.size / 1024)}KB`,
|
|
4315
|
+
duration: `${stats.duration}ms`
|
|
4316
|
+
});
|
|
4317
|
+
}
|
|
4318
|
+
})
|
|
4319
|
+
]
|
|
4320
|
+
});
|
|
4321
|
+
|
|
4322
|
+
await s3db.connect();
|
|
4323
|
+
|
|
4324
|
+
// Perform backups
|
|
4325
|
+
const fullBackup = await s3db.plugins.backup.backup('full');
|
|
4326
|
+
console.log('Backup ID:', fullBackup.id);
|
|
4327
|
+
|
|
4328
|
+
const incrementalBackup = await s3db.plugins.backup.backup('incremental');
|
|
4329
|
+
|
|
4330
|
+
// List available backups
|
|
4331
|
+
const backups = await s3db.plugins.backup.listBackups();
|
|
4332
|
+
console.log('Available backups:', backups.length);
|
|
4333
|
+
|
|
4334
|
+
// Restore from backup
|
|
4335
|
+
// await s3db.plugins.backup.restore(fullBackup.id);
|
|
4336
|
+
```
|
|
4337
|
+
|
|
4338
|
+
### ⚙️ Configuration Parameters
|
|
4339
|
+
|
|
4340
|
+
| Parameter | Type | Default | Description |
|
|
4341
|
+
|-----------|------|---------|-------------|
|
|
4342
|
+
| `destinations` | array | `[]` | Backup destinations configuration |
|
|
4343
|
+
| `retention` | object | `{}` | Retention policy (daily, weekly, monthly, yearly) |
|
|
4344
|
+
| `include` | array | `null` | Resources to include (null = all) |
|
|
4345
|
+
| `exclude` | array | `[]` | Resources to exclude (supports wildcards) |
|
|
4346
|
+
| `compression` | string | `'gzip'` | Compression: `'none'`, `'gzip'`, `'brotli'` |
|
|
4347
|
+
| `encryption` | object | `null` | Encryption configuration |
|
|
4348
|
+
| `verification` | boolean | `true` | Verify backup integrity |
|
|
4349
|
+
| `tempDir` | string | `'./tmp/backups'` | Temporary working directory |
|
|
4350
|
+
| `onBackupStart` | function | `null` | Callback when backup starts |
|
|
4351
|
+
| `onBackupComplete` | function | `null` | Callback when backup completes |
|
|
4352
|
+
| `onBackupError` | function | `null` | Callback when backup fails |
|
|
4353
|
+
| `verbose` | boolean | `false` | Enable detailed logging |
|
|
4354
|
+
|
|
4355
|
+
### Destination Types
|
|
4356
|
+
|
|
4357
|
+
#### Filesystem
|
|
4358
|
+
```javascript
|
|
4359
|
+
{
|
|
4360
|
+
type: 'filesystem',
|
|
4361
|
+
path: '/backups/{date}/', // {date} expands to YYYY-MM-DD
|
|
4362
|
+
compression: 'gzip'
|
|
4363
|
+
}
|
|
4364
|
+
```
|
|
4365
|
+
|
|
4366
|
+
#### Amazon S3
|
|
4367
|
+
```javascript
|
|
4368
|
+
{
|
|
4369
|
+
type: 's3',
|
|
4370
|
+
bucket: 'backup-bucket',
|
|
4371
|
+
path: 'db-backups/{date}/',
|
|
4372
|
+
region: 'us-east-1',
|
|
4373
|
+
storageClass: 'STANDARD_IA'
|
|
4374
|
+
}
|
|
4375
|
+
```
|
|
4376
|
+
|
|
4377
|
+
### Backup Types
|
|
4378
|
+
|
|
4379
|
+
```javascript
|
|
4380
|
+
// Full backup - complete snapshot
|
|
4381
|
+
const fullBackup = await backup.backup('full');
|
|
4382
|
+
|
|
4383
|
+
// Incremental backup - changes since last backup
|
|
4384
|
+
const incrementalBackup = await backup.backup('incremental');
|
|
4385
|
+
|
|
4386
|
+
// Differential backup - changes since last full backup
|
|
4387
|
+
const differentialBackup = await backup.backup('differential');
|
|
4388
|
+
```
|
|
4389
|
+
|
|
4390
|
+
### Retention Policies (GFS)
|
|
4391
|
+
|
|
4392
|
+
```javascript
|
|
4393
|
+
retention: {
|
|
4394
|
+
daily: 7, // Keep daily backups for 7 days
|
|
4395
|
+
weekly: 4, // Keep weekly backups for 4 weeks
|
|
4396
|
+
monthly: 12, // Keep monthly backups for 12 months
|
|
4397
|
+
yearly: 3 // Keep yearly backups for 3 years
|
|
4398
|
+
}
|
|
4399
|
+
```
|
|
4400
|
+
|
|
4401
|
+
### API Methods
|
|
4402
|
+
|
|
4403
|
+
```javascript
|
|
4404
|
+
// Backup operations
|
|
4405
|
+
const result = await backup.backup(type, options);
|
|
4406
|
+
const backups = await backup.listBackups({ type: 'full', limit: 10 });
|
|
4407
|
+
const status = await backup.getBackupStatus(backupId);
|
|
4408
|
+
await backup.restore(backupId, options);
|
|
4409
|
+
|
|
4410
|
+
// Management
|
|
4411
|
+
await backup.cleanup(); // Apply retention policy
|
|
4412
|
+
const isValid = await backup.verify(backupId);
|
|
4413
|
+
await backup.cancel(backupId);
|
|
4414
|
+
```
|
|
4415
|
+
|
|
4416
|
+
### Events
|
|
4417
|
+
|
|
4418
|
+
```javascript
|
|
4419
|
+
backup.on('backup_start', ({ id, type }) => {
|
|
4420
|
+
console.log(`Backup ${id} started (${type})`);
|
|
4421
|
+
});
|
|
4422
|
+
|
|
4423
|
+
backup.on('backup_complete', ({ id, type, size, duration, destinations }) => {
|
|
4424
|
+
console.log(`Backup ${id} completed in ${duration}ms`);
|
|
4425
|
+
});
|
|
4426
|
+
|
|
4427
|
+
backup.on('backup_error', ({ id, type, error }) => {
|
|
4428
|
+
console.error(`Backup ${id} failed:`, error);
|
|
4429
|
+
});
|
|
4430
|
+
```
|
|
4431
|
+
|
|
4432
|
+
---
|
|
4433
|
+
|
|
4434
|
+
## ⏰ Scheduler Plugin
|
|
4435
|
+
|
|
4436
|
+
Robust job scheduling capabilities with cron expressions, retry logic, and comprehensive monitoring for automated tasks.
|
|
4437
|
+
|
|
4438
|
+
### ⚡ Quick Start
|
|
4439
|
+
|
|
4440
|
+
```javascript
|
|
4441
|
+
import { S3db, SchedulerPlugin } from 's3db.js';
|
|
4442
|
+
|
|
4443
|
+
const s3db = new S3db({
|
|
4444
|
+
connectionString: "s3://ACCESS_KEY:SECRET_KEY@BUCKET_NAME/databases/myapp",
|
|
4445
|
+
plugins: [
|
|
4446
|
+
new SchedulerPlugin({
|
|
4447
|
+
timezone: 'America/Sao_Paulo',
|
|
4448
|
+
jobs: {
|
|
4449
|
+
daily_cleanup: {
|
|
4450
|
+
schedule: '0 3 * * *', // 3 AM daily
|
|
4451
|
+
description: 'Clean up expired sessions',
|
|
4452
|
+
action: async (database, context) => {
|
|
4453
|
+
const expired = await database.resource('sessions').list({
|
|
4454
|
+
where: { expiresAt: { $lt: new Date() } }
|
|
4455
|
+
});
|
|
4456
|
+
|
|
4457
|
+
for (const session of expired) {
|
|
4458
|
+
await database.resource('sessions').delete(session.id);
|
|
4459
|
+
}
|
|
4460
|
+
|
|
4461
|
+
return { deleted: expired.length };
|
|
4462
|
+
},
|
|
4463
|
+
enabled: true,
|
|
4464
|
+
retries: 2,
|
|
4465
|
+
timeout: 30000
|
|
4466
|
+
},
|
|
4467
|
+
|
|
4468
|
+
hourly_metrics: {
|
|
4469
|
+
schedule: '@hourly',
|
|
4470
|
+
description: 'Collect system metrics',
|
|
4471
|
+
action: async (database) => {
|
|
4472
|
+
const metrics = {
|
|
4473
|
+
timestamp: new Date().toISOString(),
|
|
4474
|
+
memory: process.memoryUsage(),
|
|
4475
|
+
uptime: process.uptime()
|
|
4476
|
+
};
|
|
4477
|
+
|
|
4478
|
+
await database.resource('metrics').insert({
|
|
4479
|
+
id: `metrics_${Date.now()}`,
|
|
4480
|
+
...metrics
|
|
4481
|
+
});
|
|
4482
|
+
|
|
4483
|
+
return metrics;
|
|
4484
|
+
}
|
|
4485
|
+
}
|
|
4486
|
+
},
|
|
4487
|
+
onJobComplete: (jobName, result, duration) => {
|
|
4488
|
+
console.log(`Job ${jobName} completed in ${duration}ms`);
|
|
4489
|
+
}
|
|
4490
|
+
})
|
|
4491
|
+
]
|
|
4492
|
+
});
|
|
4493
|
+
|
|
4494
|
+
await s3db.connect();
|
|
4495
|
+
|
|
4496
|
+
// Jobs run automatically based on schedule
|
|
4497
|
+
// Manual execution
|
|
4498
|
+
await s3db.plugins.scheduler.runJob('daily_cleanup');
|
|
4499
|
+
|
|
4500
|
+
// Get job status
|
|
4501
|
+
const allJobs = s3db.plugins.scheduler.getAllJobsStatus();
|
|
4502
|
+
console.log('Scheduled jobs:', allJobs.length);
|
|
4503
|
+
```
|
|
4504
|
+
|
|
4505
|
+
### ⚙️ Configuration Parameters
|
|
4506
|
+
|
|
4507
|
+
| Parameter | Type | Default | Description |
|
|
4508
|
+
|-----------|------|---------|-------------|
|
|
4509
|
+
| `timezone` | string | `'UTC'` | IANA timezone identifier |
|
|
4510
|
+
| `jobs` | object | `{}` | Job definitions |
|
|
4511
|
+
| `defaultTimeout` | number | `60000` | Default job timeout (ms) |
|
|
4512
|
+
| `defaultRetries` | number | `1` | Default retry attempts |
|
|
4513
|
+
| `persistJobs` | boolean | `true` | Store job execution history |
|
|
4514
|
+
| `jobHistoryResource` | string | `'job_history'` | Resource for job history |
|
|
4515
|
+
| `onJobStart` | function | `null` | Callback when job starts |
|
|
4516
|
+
| `onJobComplete` | function | `null` | Callback when job completes |
|
|
4517
|
+
| `onJobError` | function | `null` | Callback when job fails |
|
|
4518
|
+
| `verbose` | boolean | `false` | Enable detailed logging |
|
|
4519
|
+
|
|
4520
|
+
### Job Configuration
|
|
4521
|
+
|
|
4522
|
+
```javascript
|
|
4523
|
+
jobs: {
|
|
4524
|
+
job_name: {
|
|
4525
|
+
schedule: '0 0 * * *', // Cron expression (required)
|
|
4526
|
+
description: 'Job description', // Human-readable description
|
|
4527
|
+
action: async (database, context, schedulerPlugin) => {
|
|
4528
|
+
// Job implementation (required)
|
|
4529
|
+
return { success: true };
|
|
4530
|
+
},
|
|
4531
|
+
enabled: true, // Enable/disable job
|
|
4532
|
+
retries: 2, // Retry attempts on failure
|
|
4533
|
+
timeout: 30000, // Timeout in milliseconds
|
|
4534
|
+
meta: { priority: 'high' } // Custom metadata
|
|
4535
|
+
}
|
|
4536
|
+
}
|
|
4537
|
+
```
|
|
4538
|
+
|
|
4539
|
+
### Cron Expressions
|
|
4540
|
+
|
|
4541
|
+
#### Standard Format
|
|
4542
|
+
```
|
|
4543
|
+
* * * * *
|
|
4544
|
+
│ │ │ │ │
|
|
4545
|
+
│ │ │ │ └─── Day of week (0-7, Sunday = 0 or 7)
|
|
4546
|
+
│ │ │ └───── Month (1-12)
|
|
4547
|
+
│ │ └─────── Day of month (1-31)
|
|
4548
|
+
│ └───────── Hour (0-23)
|
|
4549
|
+
└─────────── Minute (0-59)
|
|
4550
|
+
```
|
|
4551
|
+
|
|
4552
|
+
#### Examples
|
|
4553
|
+
```javascript
|
|
4554
|
+
'0 0 * * *' // Daily at midnight
|
|
4555
|
+
'0 9 * * MON' // Every Monday at 9 AM
|
|
4556
|
+
'*/15 * * * *' // Every 15 minutes
|
|
4557
|
+
'0 2 1 * *' // First day of month at 2 AM
|
|
4558
|
+
```
|
|
4559
|
+
|
|
4560
|
+
#### Shorthand Expressions
|
|
4561
|
+
```javascript
|
|
4562
|
+
'@yearly' // Once a year at midnight on January 1st
|
|
4563
|
+
'@monthly' // Once a month at midnight on the 1st
|
|
4564
|
+
'@weekly' // Once a week at midnight on Sunday
|
|
4565
|
+
'@daily' // Once a day at midnight
|
|
4566
|
+
'@hourly' // Once an hour at the beginning of the hour
|
|
4567
|
+
```
|
|
4568
|
+
|
|
4569
|
+
### API Methods
|
|
4570
|
+
|
|
4571
|
+
```javascript
|
|
4572
|
+
// Job execution
|
|
4573
|
+
const result = await scheduler.runJob(jobName, context);
|
|
4574
|
+
const stats = scheduler.getJobStatus(jobName);
|
|
4575
|
+
const allJobs = scheduler.getAllJobsStatus();
|
|
4576
|
+
|
|
4577
|
+
// Job management
|
|
4578
|
+
scheduler.enableJob(jobName);
|
|
4579
|
+
scheduler.disableJob(jobName);
|
|
4580
|
+
scheduler.addJob(jobName, jobConfig);
|
|
4581
|
+
scheduler.removeJob(jobName);
|
|
4582
|
+
|
|
4583
|
+
// History and monitoring
|
|
4584
|
+
const history = await scheduler.getJobHistory(jobName, { status: 'success', limit: 10 });
|
|
4585
|
+
const stats = scheduler.getJobStatistics(jobName);
|
|
4586
|
+
```
|
|
4587
|
+
|
|
4588
|
+
### Events
|
|
4589
|
+
|
|
4590
|
+
```javascript
|
|
4591
|
+
scheduler.on('job_start', ({ jobName, context }) => {
|
|
4592
|
+
console.log(`Job ${jobName} started`);
|
|
4593
|
+
});
|
|
4594
|
+
|
|
4595
|
+
scheduler.on('job_complete', ({ jobName, result, duration }) => {
|
|
4596
|
+
console.log(`Job ${jobName} completed in ${duration}ms`);
|
|
4597
|
+
});
|
|
4598
|
+
|
|
4599
|
+
scheduler.on('job_error', ({ jobName, error, retryCount }) => {
|
|
4600
|
+
console.error(`Job ${jobName} failed (attempt ${retryCount}):`, error);
|
|
4601
|
+
});
|
|
4602
|
+
|
|
4603
|
+
scheduler.on('job_enabled', ({ jobName }) => {
|
|
4604
|
+
console.log(`Job ${jobName} enabled`);
|
|
4605
|
+
});
|
|
4606
|
+
```
|
|
4607
|
+
|
|
4608
|
+
### Integration with Other Plugins
|
|
4609
|
+
|
|
4610
|
+
```javascript
|
|
4611
|
+
// Scheduled backups
|
|
4612
|
+
jobs: {
|
|
4613
|
+
daily_backup: {
|
|
4614
|
+
schedule: '0 1 * * *',
|
|
4615
|
+
action: async (database) => {
|
|
4616
|
+
const backup = database.getPlugin('BackupPlugin');
|
|
4617
|
+
return await backup.backup('full');
|
|
4618
|
+
}
|
|
4619
|
+
}
|
|
4620
|
+
}
|
|
4621
|
+
|
|
4622
|
+
// Process state machine entities
|
|
4623
|
+
jobs: {
|
|
4624
|
+
process_pending_orders: {
|
|
4625
|
+
schedule: '*/10 * * * *',
|
|
4626
|
+
action: async (database) => {
|
|
4627
|
+
const stateMachine = database.getPlugin('StateMachinePlugin');
|
|
4628
|
+
const orders = await database.resource('orders').list({
|
|
4629
|
+
where: { status: 'pending' }
|
|
4630
|
+
});
|
|
4631
|
+
|
|
4632
|
+
for (const order of orders) {
|
|
4633
|
+
await stateMachine.send('order_processing', order.id, 'AUTO_PROCESS');
|
|
4634
|
+
}
|
|
4635
|
+
|
|
4636
|
+
return { processed: orders.length };
|
|
4637
|
+
}
|
|
4638
|
+
}
|
|
4639
|
+
}
|
|
4640
|
+
```
|
|
4641
|
+
|
|
4642
|
+
---
|
|
4643
|
+
|
|
4146
4644
|
## 🎯 Best Practices
|
|
4147
4645
|
|
|
4148
4646
|
### Plugin Performance
|
|
@@ -4152,6 +4650,9 @@ const s3db = new S3db({
|
|
|
4152
4650
|
3. **Use appropriate sampling** for metrics collection
|
|
4153
4651
|
4. **Configure retention policies** for audit logs
|
|
4154
4652
|
5. **Test replicator connections** before deployment
|
|
4653
|
+
6. **Design efficient state machines** with minimal guards and actions
|
|
4654
|
+
7. **Schedule backups during low-traffic periods** to minimize impact
|
|
4655
|
+
8. **Use appropriate job timeouts** to prevent resource exhaustion
|
|
4155
4656
|
|
|
4156
4657
|
### Plugin Security
|
|
4157
4658
|
|
|
@@ -4160,6 +4661,9 @@ const s3db = new S3db({
|
|
|
4160
4661
|
3. **Use IAM roles** instead of access keys when possible
|
|
4161
4662
|
4. **Encrypt replication data** in transit and at rest
|
|
4162
4663
|
5. **Validate message sources** in queue consumers
|
|
4664
|
+
6. **Secure state machine actions** to prevent unauthorized transitions
|
|
4665
|
+
7. **Encrypt backup data** for sensitive databases
|
|
4666
|
+
8. **Restrict job execution permissions** to necessary resources only
|
|
4163
4667
|
|
|
4164
4668
|
### Plugin Monitoring
|
|
4165
4669
|
|
|
@@ -4168,6 +4672,9 @@ const s3db = new S3db({
|
|
|
4168
4672
|
3. **Track error rates** across all plugins
|
|
4169
4673
|
4. **Use structured logging** for debugging
|
|
4170
4674
|
5. **Implement circuit breakers** for external services
|
|
4675
|
+
6. **Monitor state machine transition rates** and error patterns
|
|
4676
|
+
7. **Track backup success rates** and storage usage
|
|
4677
|
+
8. **Alert on job failures** and execution delays
|
|
4171
4678
|
|
|
4172
4679
|
---
|
|
4173
4680
|
|
package/README.md
CHANGED
|
@@ -309,15 +309,6 @@ const s3db = new S3db({
|
|
|
309
309
|
});
|
|
310
310
|
```
|
|
311
311
|
|
|
312
|
-
#### Performance Impact
|
|
313
|
-
|
|
314
|
-
| Configuration | Use Case | Performance | Resource Usage |
|
|
315
|
-
|---------------|----------|-------------|----------------|
|
|
316
|
-
| **Default** | Most applications | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
|
|
317
|
-
| **High Concurrency** | APIs, web services | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
|
|
318
|
-
| **Aggressive** | Data processing, bulk ops | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
|
319
|
-
| **Conservative** | Serverless, IoT | ⭐⭐⭐ | ⭐⭐ |
|
|
320
|
-
|
|
321
312
|
### Authentication Methods
|
|
322
313
|
|
|
323
314
|
<details>
|
|
@@ -396,7 +387,20 @@ Built-in validation using [@icebob/fastest-validator](https://github.com/icebob/
|
|
|
396
387
|
|
|
397
388
|
### 🚀 Performance Optimization
|
|
398
389
|
|
|
399
|
-
s3db.js
|
|
390
|
+
s3db.js uses advanced encoding techniques to minimize S3 metadata usage and maximize performance:
|
|
391
|
+
|
|
392
|
+
#### Metadata Encoding Optimizations
|
|
393
|
+
|
|
394
|
+
| Optimization | Space Saved | Example |
|
|
395
|
+
|-------------|-------------|---------|
|
|
396
|
+
| **ISO Timestamps** | 67% | `2024-01-15T10:30:00Z` → `ism8LiNFkz90` |
|
|
397
|
+
| **UUIDs** | 33% | `550e8400-e29b-41d4-a716-446655440000` → `uVQ6EAOKbQdShbkRmRUQAAA==` |
|
|
398
|
+
| **Dictionary Values** | 95% | `active` → `da` |
|
|
399
|
+
| **Hex Strings** | 33% | MD5/SHA hashes compressed with base64 |
|
|
400
|
+
| **Large Numbers** | 40-46% | Unix timestamps with base62 encoding |
|
|
401
|
+
| **UTF-8 Memory Cache** | 2-3x faster | Cached byte calculations |
|
|
402
|
+
|
|
403
|
+
Total metadata savings: **40-50%** on typical datasets.
|
|
400
404
|
|
|
401
405
|
#### Bulk Operations Performance
|
|
402
406
|
|