Skip to content

Compute Functions

Overview

Compute Functions are serverless functions that run within Centrali's secure sandbox environment. They can be triggered by events, scheduled to run at specific times, or invoked on-demand.

What are Compute Functions?

Compute functions allow you to: - Process data: Transform, validate, or enrich records - Automate workflows: React to data changes automatically - Integrate systems: Call external APIs and services - Run scheduled tasks: Periodic data cleanup, reports, backups - Implement business logic: Custom calculations and validations

Key Features

Secure Sandbox

  • Functions run in isolated environments
  • No access to file system or network (except approved APIs)
  • CPU and memory limits enforced
  • Automatic timeout after 5 minutes

Built-in APIs

Functions have access to: - Data API: Query and modify records in your workspace - Storage API: Upload and download files - HTTP Client: Make external API calls - Logging: Built-in logger for debugging

Event-Driven

Functions can be triggered by: - Record events: Created, updated, deleted - Schedule: Cron expressions for periodic execution - Manual: On-demand invocation via API - Webhooks: External HTTP requests

Creating a Function

Step 1: Define the Function

curl -X POST https://api.centrali.io/workspace/my-workspace/api/v1/functions \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "process-order",
    "description": "Process new orders and send notifications",
    "runtime": "nodejs-20"
  }'

Response:

{
  "id": "func_abc123",
  "name": "process-order",
  "status": "draft",
  "version": 1
}

Step 2: Upload Function Code

curl -X PUT https://api.centrali.io/workspace/my-workspace/api/v1/functions/func_abc123/code \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "export async function handler(event, context) {\n  const { recordId } = event;\n  \n  // Query the order record\n  const order = await context.data.getRecord(\"orders\", recordId);\n  \n  // Call external API\n  await context.http.post(\"https://api.example.com/notify\", {\n    orderId: order.id,\n    total: order.total\n  });\n  \n  return { success: true };\n}"
  }'

Step 3: Test the Function

curl -X POST https://api.centrali.io/workspace/my-workspace/api/v1/functions/func_abc123/test \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "event": {
      "recordId": "rec_order_123"
    }
  }'

Step 4: Publish the Function

curl -X POST https://api.centrali.io/workspace/my-workspace/api/v1/functions/func_abc123/publish \
  -H "Authorization: Bearer YOUR_TOKEN"

Function Code Structure

Basic Handler

export async function handler(event, context) {
  // Your code here

  return {
    success: true,
    data: { /* your results */ }
  };
}

Event Object

The event parameter contains trigger-specific data:

Record Event:

{
  "type": "record.created",
  "structureName": "orders",
  "recordId": "rec_abc123",
  "record": { /* full record data */ }
}

Scheduled Event:

{
  "type": "schedule",
  "scheduledTime": "2025-01-15T10:00:00Z"
}

Manual Invocation:

{
  "type": "manual",
  "payload": { /* custom data */ }
}

Context Object

The context parameter provides APIs:

{
  // Data API
  data: {
    getRecord(structure, id),
    queryRecords(structure, query),
    createRecord(structure, data),
    updateRecord(structure, id, updates),
    deleteRecord(structure, id)
  },

  // HTTP Client
  http: {
    get(url, options),
    post(url, data, options),
    put(url, data, options),
    delete(url, options)
  },

  // Storage API
  storage: {
    upload(fileName, data),
    download(fileName),
    delete(fileName),
    list(prefix)
  },

  // Logger
  logger: {
    info(message, data),
    warn(message, data),
    error(message, data)
  },

  // Environment
  env: {
    // Access to function parameters (secrets, config)
  }
}

Function Examples

Example 1: Send Welcome Email

export async function handler(event, context) {
  const { record } = event;

  // Send welcome email via external service
  await context.http.post('https://api.sendgrid.com/v3/mail/send', {
    to: record.email,
    subject: 'Welcome!',
    text: `Hello ${record.name}, welcome to our platform!`
  }, {
    headers: {
      'Authorization': `Bearer ${context.env.SENDGRID_API_KEY}`
    }
  });

  context.logger.info('Welcome email sent', { userId: record.id });

  return { success: true };
}

Example 2: Calculate Order Total

export async function handler(event, context) {
  const { recordId } = event;

  // Get order with line items
  const order = await context.data.getRecord('orders', recordId);

  // Calculate total
  let total = 0;
  for (const item of order.items) {
    const product = await context.data.getRecord('products', item.productId);
    total += product.price * item.quantity;
  }

  // Update order with calculated total
  await context.data.updateRecord('orders', recordId, { total });

  return { success: true, total };
}

Example 3: Scheduled Cleanup

export async function handler(event, context) {
  // Delete records older than 30 days
  const thirtyDaysAgo = new Date();
  thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

  const oldRecords = await context.data.queryRecords('logs', {
    filter: `createdAt < "${thirtyDaysAgo.toISOString()}"`
  });

  for (const record of oldRecords) {
    await context.data.deleteRecord('logs', record.id);
  }

  context.logger.info('Cleanup complete', { deleted: oldRecords.length });

  return { deleted: oldRecords.length };
}

Function Parameters

Store secrets and configuration as function parameters:

Adding Parameters

curl -X PUT https://api.centrali.io/workspace/my-workspace/api/v1/functions/func_abc123/parameters \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "parameters": {
      "API_KEY": {
        "value": "sk_live_abc123",
        "encrypted": true
      },
      "WEBHOOK_URL": {
        "value": "https://api.example.com/webhook",
        "encrypted": false
      }
    }
  }'

Accessing Parameters

export async function handler(event, context) {
  const apiKey = context.env.API_KEY;
  const webhookUrl = context.env.WEBHOOK_URL;

  // Use parameters in your code
}

Triggers

See the Function Triggers API for complete documentation.

Record Trigger

Run function when records are created/updated/deleted:

curl -X POST https://api.centrali.io/workspace/my-workspace/api/v1/triggers \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "process-new-orders",
    "functionId": "func_abc123",
    "type": "record",
    "config": {
      "structure": "orders",
      "events": ["created"]
    }
  }'

Schedule Trigger

Run function on a schedule (cron):

curl -X POST https://api.centrali.io/workspace/my-workspace/api/v1/triggers \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "daily-cleanup",
    "functionId": "func_abc123",
    "type": "schedule",
    "config": {
      "cron": "0 2 * * *"
    }
  }'

Common Cron Examples: - 0 * * * * - Every hour - 0 0 * * * - Daily at midnight - 0 9 * * 1 - Every Monday at 9 AM - */15 * * * * - Every 15 minutes

Manual Trigger

Invoke function via API:

curl -X POST https://api.centrali.io/workspace/my-workspace/api/v1/functions/func_abc123/invoke \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "payload": {
      "customData": "value"
    }
  }'

Monitoring & Debugging

View Function Runs

curl -X GET https://api.centrali.io/workspace/my-workspace/api/v1/functions/func_abc123/runs \
  -H "Authorization: Bearer YOUR_TOKEN"

Response:

{
  "runs": [
    {
      "id": "run_xyz789",
      "status": "completed",
      "startedAt": "2025-01-15T10:00:00Z",
      "completedAt": "2025-01-15T10:00:05Z",
      "duration": 5000,
      "result": { "success": true }
    }
  ]
}

View Run Logs

curl -X GET https://api.centrali.io/workspace/my-workspace/api/v1/functions/func_abc123/runs/run_xyz789/logs \
  -H "Authorization: Bearer YOUR_TOKEN"

Re-run Failed Functions

See Function Re-run documentation.

Best Practices

Code Organization

  • Keep functions focused on a single task
  • Extract reusable logic to helper functions
  • Use clear variable and function names
  • Add comments for complex logic

Error Handling

export async function handler(event, context) {
  try {
    // Your code here
    return { success: true };
  } catch (error) {
    context.logger.error('Function failed', { error: error.message });
    throw error; // Re-throw to mark run as failed
  }
}

Performance

  • Minimize external API calls
  • Cache frequently accessed data
  • Use bulk operations for multiple records
  • Set appropriate timeout limits

Security

  • Store secrets as encrypted parameters
  • Validate input data
  • Use HTTPS for external calls
  • Follow principle of least privilege

Limits & Quotas

Default limits: - Execution time: 5 minutes maximum - Memory: 512 MB - Concurrent runs: 10 per function - Code size: 10 MB - External HTTP calls: 100 per execution

Next Steps

  1. Write your first function
  2. Set up triggers
  3. Learn the code API
  4. Configure webhooks