Action System Overview
The Action System is the heart of the MuluTime Plugin SDK, providing a declarative way to handle events, schedules, and API endpoints through decorators.
Key Conceptsβ
π― Declarative Programmingβ
Instead of manually registering handlers, use decorators to declare what your plugin responds to:
@OnEvent(SystemEventType.BOOKING_CREATED)
async handleBooking(event: SystemEventPayload, context: PluginContext) {
// Handle booking creation
}
π Automatic Registrationβ
The SDK automatically discovers and registers your decorated methods when the plugin loads.
π‘οΈ Built-in Protectionβ
- Error handling and retry logic
- Permission checking
- Timeout protection
- Validation
Action Typesβ
1. Event Actionsβ
React to system events like bookings, user actions, or custom events.
import { OnEvent, SystemEventType } from '@mulutime/plugin-sdk';
@OnEvent(SystemEventType.BOOKING_CREATED)
async onBookingCreated(event: SystemEventPayload, context: PluginContext) {
// Handle the event
}
2. Scheduled Actionsβ
Execute code on a schedule using cron expressions or predefined intervals.
import { Scheduled, PluginScheduleType } from '@mulutime/plugin-sdk';
@Scheduled(PluginScheduleType.DAILY, { time: '09:00' })
async dailyReport(context: PluginContext) {
// Generate daily report
}
3. API Actionsβ
Expose HTTP endpoints that external systems can call.
import { Get, Post } from '@mulutime/plugin-sdk';
@Get('/status')
async getStatus(request: APIRequest, context: PluginContext): Promise<APIResponse> {
return { status: 200, data: { status: 'ok' } };
}
4. Lifecycle Actionsβ
Handle plugin lifecycle events like installation, updates, and configuration changes.
import { OnInstall, OnUpdate } from '@mulutime/plugin-sdk';
@OnInstall()
async handleInstall(context: PluginContext) {
// Initialize plugin
}
Advanced Featuresβ
Filtering and Conditionsβ
Add conditions to control when actions execute:
@OnEvent(SystemEventType.BOOKING_CREATED, {
filters: {
organizationId: 'org-123',
conditions: {
'data.service.category': 'premium',
'data.amount': { $gt: 100 }
}
}
})
async handlePremiumBooking(event: SystemEventPayload, context: PluginContext) {
// Only executes for premium bookings over $100 in org-123
}
Priority and Orderingβ
Control execution order with priority levels:
@OnEvent(SystemEventType.BOOKING_CREATED, { priority: 1 })
async highPriorityHandler(event: SystemEventPayload, context: PluginContext) {
// Executes first
}
@OnEvent(SystemEventType.BOOKING_CREATED, { priority: 10 })
async lowPriorityHandler(event: SystemEventPayload, context: PluginContext) {
// Executes later
}
Retry Logicβ
Configure automatic retries for failed actions:
@OnEvent(SystemEventType.BOOKING_CREATED, {
retry: {
attempts: 3,
delay: 1000,
backoff: 'exponential'
}
})
async reliableHandler(event: SystemEventPayload, context: PluginContext) {
// Will retry up to 3 times with exponential backoff
}
Timeout Protectionβ
Set timeouts to prevent long-running actions:
@OnEvent(SystemEventType.BOOKING_CREATED, {
timeout: 30000 // 30 seconds
})
async timedHandler(event: SystemEventPayload, context: PluginContext) {
// Will timeout after 30 seconds
}
Complete Exampleβ
Here's a comprehensive example showing all action types:
import {
BasePlugin,
OnEvent,
Scheduled,
Get,
Post,
OnInstall,
OnUpdate,
SystemEventType,
PluginScheduleType,
PluginManifest,
PluginCategory,
PluginPermission,
APIRequest,
APIResponse,
PluginContext,
SystemEventPayload
} from '@mulutime/plugin-sdk';
export class ComprehensivePlugin extends BasePlugin {
manifest: PluginManifest = {
id: 'com.example.comprehensive',
name: 'Comprehensive Plugin',
version: '1.0.0',
description: 'Demonstrates all action types',
author: { name: 'Developer', email: 'dev@example.com' },
category: PluginCategory.INTEGRATION,
permissions: [
PluginPermission.READ_BOOKING_DATA,
PluginPermission.EXTERNAL_API_ACCESS
],
apiVersion: '1.0.0',
minSystemVersion: '1.0.0',
main: 'dist/index.js'
};
// Lifecycle Actions
@OnInstall()
async handleInstall(context: PluginContext) {
const sdk = this.getSDK();
await sdk.storage.set('installed-at', new Date().toISOString());
sdk.logger.info('Plugin installed');
}
@OnUpdate()
async handleUpdate(context: PluginContext, oldVersion: string) {
const sdk = this.getSDK();
sdk.logger.info(`Updated from ${oldVersion} to ${this.manifest.version}`);
}
// Event Actions
@OnEvent(SystemEventType.BOOKING_CREATED, {
priority: 1,
filters: {
conditions: {
'data.service.category': 'premium'
}
}
})
async handlePremiumBooking(event: SystemEventPayload, context: PluginContext) {
const sdk = this.getSDK();
sdk.logger.info(`Premium booking created: ${event.data.id}`);
// Send VIP notification
await this.sendVIPNotification(event.data);
}
@OnEvent([
SystemEventType.BOOKING_UPDATED,
SystemEventType.BOOKING_CANCELLED
])
async handleBookingChanges(event: SystemEventPayload, context: PluginContext) {
const sdk = this.getSDK();
sdk.logger.info(`Booking ${event.type}: ${event.data.id}`);
}
// Scheduled Actions
@Scheduled(PluginScheduleType.DAILY, { time: '09:00' })
async generateDailyReport(context: PluginContext) {
const sdk = this.getSDK();
sdk.logger.info('Generating daily report');
// Generate and send report
const report = await this.createDailyReport();
await this.sendReport(report);
}
@Scheduled(PluginScheduleType.CUSTOM, {
cronExpression: '0 */6 * * *' // Every 6 hours
})
async performMaintenance(context: PluginContext) {
const sdk = this.getSDK();
sdk.logger.info('Performing maintenance tasks');
// Cleanup old data
await this.cleanupOldData();
}
// API Actions
@Get('/stats')
async getStats(request: APIRequest, context: PluginContext): Promise<APIResponse> {
const sdk = this.getSDK();
const stats = await sdk.storage.get('plugin-stats') || { requests: 0 };
return {
status: 200,
data: stats
};
}
@Post('/webhook', {
validation: {
body: {
type: 'object',
properties: {
event: { type: 'string' },
data: { type: 'object' }
},
required: ['event', 'data']
}
}
})
async handleWebhook(request: APIRequest, context: PluginContext): Promise<APIResponse> {
const sdk = this.getSDK();
// Process webhook
sdk.logger.info(`Webhook received: ${request.body.event}`);
await this.processWebhookEvent(request.body);
return { status: 200, data: { received: true } };
}
// Helper methods
private async sendVIPNotification(bookingData: any) {
// Implementation
}
private async createDailyReport() {
// Implementation
return { date: new Date().toISOString(), bookings: 0 };
}
private async sendReport(report: any) {
// Implementation
}
private async cleanupOldData() {
// Implementation
}
private async processWebhookEvent(event: any) {
// Implementation
}
}
Best Practicesβ
β Do'sβ
- Use meaningful method names that describe the action
- Add proper error handling in action methods
- Use filters to reduce unnecessary executions
- Set appropriate timeouts for long-running actions
- Log important events for debugging
β Don'tsβ
- Don't perform heavy computations in event handlers
- Don't make actions dependent on execution order (except with priorities)
- Don't ignore errors without proper handling
- Don't use blocking operations without timeouts
Debugging Actionsβ
Enable Action Loggingβ
// In your plugin's onInstall method
const sdk = this.getSDK();
await sdk.storage.set('debug-actions', true);
View Action Executionβ
The SDK provides built-in logging for action execution:
// Logs will show:
// - Action type and method name
// - Execution time
// - Success/failure status
// - Error details if failed
Performance Considerationsβ
- Event Filtering: Use filters to reduce unnecessary executions
- Async Operations: Always use async/await for I/O operations
- Timeout Settings: Set appropriate timeouts for external calls
- Retry Logic: Configure retries for unreliable operations
- Resource Cleanup: Clean up resources in lifecycle handlers
The Action System provides a powerful, declarative way to build reactive plugins that respond to events, run on schedules, and expose APIsβall with built-in reliability and error handling.