Skip to main content

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​

  1. Event Filtering: Use filters to reduce unnecessary executions
  2. Async Operations: Always use async/await for I/O operations
  3. Timeout Settings: Set appropriate timeouts for external calls
  4. Retry Logic: Configure retries for unreliable operations
  5. 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.