diff --git a/development/backend/job-queue.mdx b/development/backend/job-queue.mdx
index 7dfe2e2..596d9ab 100644
--- a/development/backend/job-queue.mdx
+++ b/development/backend/job-queue.mdx
@@ -30,7 +30,7 @@ Background worker loop that polls the database every second, processes jobs sequ
Plugin-style pattern where each worker implements the `Worker` interface. Workers are registered by type (e.g., `send_email`, `process_csv`, `sync_registry`) and execute specific job types.
### Database Tables
-Two tables provide persistence: `queueJobs` stores individual jobs with payload and status, while `queueJobBatches` tracks groups of related jobs for progress monitoring.
+Two tables provide persistence: `queueJobs` stores individual jobs with payload, status, and result data, while `queueJobBatches` tracks groups of related jobs for progress monitoring.
## Core Concepts
@@ -92,10 +92,12 @@ interface Worker {
interface WorkerResult {
success: boolean;
message?: string;
- data?: any;
+ data?: any; // Persisted to database on job completion
}
```
+The `data` field in `WorkerResult` is automatically stored in the database when a job completes successfully. This allows you to inspect job results through the admin UI or database queries.
+
### Basic Worker Pattern
```typescript
@@ -136,7 +138,8 @@ export class EmailWorker implements Worker {
return {
success: true,
- message: 'Email sent successfully'
+ message: 'Email sent successfully',
+ data: { sentAt: new Date().toISOString(), recipient: emailPayload.to }
};
} catch (error) {
this.logger.error({
@@ -365,25 +368,25 @@ Jobs transition through these states:
### Database Queries
-Check job status:
+Check job status and result:
```sql
-SELECT id, type, status, created_at, started_at, completed_at, attempts
-FROM queue_jobs
+SELECT id, type, status, payload, result, error, created_at, completed_at, attempts
+FROM "queueJobs"
WHERE id = ?;
```
Monitor batch progress:
```sql
-SELECT
+SELECT
b.id,
b.total_jobs,
COUNT(CASE WHEN j.status = 'completed' THEN 1 END) as completed,
COUNT(CASE WHEN j.status = 'failed' THEN 1 END) as failed,
COUNT(CASE WHEN j.status = 'processing' THEN 1 END) as processing
-FROM queue_job_batches b
-LEFT JOIN queue_jobs j ON j.batch_id = b.id
+FROM "queueJobBatches" b
+LEFT JOIN "queueJobs" j ON j.batch_id = b.id
WHERE b.id = ?
GROUP BY b.id;
```
@@ -414,32 +417,42 @@ For the complete database schema, see [schema.ts](https://github.com/deploystack
### Jobs Table
```sql
-CREATE TABLE queue_jobs (
+CREATE TABLE "queueJobs" (
id TEXT PRIMARY KEY,
type TEXT NOT NULL,
- payload TEXT,
+ payload TEXT NOT NULL,
status TEXT DEFAULT 'pending',
+ scheduled_for TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
attempts INTEGER DEFAULT 0,
max_attempts INTEGER DEFAULT 3,
- scheduled_for INTEGER,
- created_at INTEGER DEFAULT (unixepoch()),
- started_at INTEGER,
- completed_at INTEGER,
- last_error TEXT,
- batch_id TEXT,
- FOREIGN KEY (batch_id) REFERENCES queue_job_batches(id)
+ error TEXT,
+ result TEXT,
+ batch_id TEXT REFERENCES "queueJobBatches"(id) ON DELETE CASCADE,
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
+ completed_at TIMESTAMP WITH TIME ZONE
);
```
+| Column | Description |
+|--------|-------------|
+| `payload` | JSON input data passed to the worker |
+| `error` | Error message if job failed |
+| `result` | JSON output data returned by the worker on success |
+
### Batches Table
```sql
-CREATE TABLE queue_job_batches (
+CREATE TABLE "queueJobBatches" (
id TEXT PRIMARY KEY,
- name TEXT NOT NULL,
+ type TEXT NOT NULL,
total_jobs INTEGER NOT NULL,
- created_at INTEGER DEFAULT (unixepoch()),
- metadata TEXT
+ completed_jobs INTEGER DEFAULT 0,
+ failed_jobs INTEGER DEFAULT 0,
+ status TEXT DEFAULT 'pending',
+ metadata TEXT,
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
+ completed_at TIMESTAMP WITH TIME ZONE
);
```
@@ -451,8 +464,8 @@ CREATE TABLE queue_job_batches (
2. Check if job's `scheduled_for` time has passed
3. Lock job by setting status to `processing`
4. Execute worker for job type
-5. Update status based on result
-6. Implement exponential backoff for retries (1s, 2s, 4s, etc.)
+5. On success: store worker's `data` in `result` column, set status to `completed`
+6. On failure: implement exponential backoff for retries (1s, 2s, 4s, etc.)
### Resource Usage
@@ -486,9 +499,12 @@ Balance between responsiveness and database load. Adequate latency for backgroun
- Not suitable for sub-second latency requirements
- Single-server deployment (no distributed workers)
-- No built-in job scheduling (cron-like patterns)
- Sequential processing limits throughput
+
+For recurring scheduled tasks, see the [Cron Job Scheduling](/development/backend/cron) documentation which integrates with this job queue system.
+
+
## Migration Path
If scaling beyond single-server becomes necessary, clear upgrade paths exist:
@@ -501,10 +517,10 @@ Worker interface remains compatible, simplifying migration.
## Related Documentation
+- [Cron Job Scheduling](/development/backend/cron) - Schedule recurring tasks using cron expressions
- [Database Management](/development/backend/database/) - Database configuration and schema
- [Global Event Bus](/development/backend/events) - Event system for real-time notifications
- [Logging](/development/backend/logging) - Logging best practices and patterns
-- [API Documentation](/development/backend/api/) - REST API endpoints and patterns
## Common Use Cases
diff --git a/development/frontend/ui/design-button-loading.mdx b/development/frontend/ui/design-button-loading.mdx
index 111de18..62ebd3d 100644
--- a/development/frontend/ui/design-button-loading.mdx
+++ b/development/frontend/ui/design-button-loading.mdx
@@ -1,43 +1,32 @@
---
title: Button with Loading States
-description: Guide for using the enhanced Button component with built-in loading states.
+description: Guide for implementing loading states in buttons using the Spinner component.
---
-The Button component includes built-in loading state functionality for async operations.
+Use the shadcn-vue Spinner component inside buttons to show loading states during async operations.
-## Component Location
+## Component Locations
```
services/frontend/src/components/ui/button/
-├── Button.vue # Enhanced button component with loading states
+├── Button.vue # Standard shadcn-vue button
└── index.ts # Button variants and exports
-```
-
-## Features
-
-- **Automatic spinner** with `Loader2` icon from lucide-vue-next
-- **Auto-disable** during loading to prevent double submissions
-- **Optional loading text** to display custom messages
-- **Size-aware spinner** that scales with button size
-- **Works with all variants** (default, destructive, outline, etc.)
-## Props
+services/frontend/src/components/ui/spinner/
+├── Spinner.vue # Animated loading spinner
+└── index.ts # Spinner exports
+```
-| Prop | Type | Default | Description |
-|------|------|---------|-------------|
-| `loading` | `boolean` | `false` | Shows spinner and disables button |
-| `loadingText` | `string` | `undefined` | Optional text during loading |
-| `disabled` | `boolean` | `false` | Disable independent of loading |
-| `variant` | `string` | `'default'` | Button style variant |
-| `size` | `string` | `'default'` | Button size (sm, default, lg, icon) |
+## Usage
-## Usage Example
+Import both Button and Spinner, then conditionally render the Spinner inside the button:
```vue
-
```
-## Implementation Details
+## Pattern
+
+The loading button pattern consists of three parts:
+
+1. **Disable the button** - Add `:disabled="isLoading"` to prevent double clicks
+2. **Show the spinner** - Add `` before the text
+3. **Keep the text visible** - The button text remains visible during loading
+
+## Spinner Customization
+
+The Spinner component accepts a `class` prop for styling:
+
+```vue
+
+
+
+
+
+```
-The component automatically:
-- Displays a spinning `Loader2` icon when `loading` is true
-- Hides the original slot content during loading
-- Shows `loadingText` alongside the spinner (if provided)
-- Disables the button to prevent multiple clicks
-- Adjusts spinner size based on button size prop
+## Examples
-For implementation details, see the source code at `services/frontend/src/components/ui/button/Button.vue`.
+### Form Submit Button
+
+```vue
+
+```
+
+### Delete Button
+
+```vue
+
+```
+
+### With Validation
+
+```vue
+
+```
## Related Documentation
diff --git a/development/frontend/ui/design-settings-menu.mdx b/development/frontend/ui/design-settings-menu.mdx
new file mode 100644
index 0000000..31949e3
Binary files /dev/null and b/development/frontend/ui/design-settings-menu.mdx differ
diff --git a/docs.json b/docs.json
index 9833c6a..82be3e2 100644
--- a/docs.json
+++ b/docs.json
@@ -100,7 +100,8 @@
"/development/frontend/ui/design-system-structured-data",
"/development/frontend/ui/design-system-table",
"/development/frontend/ui/custom-ui-components",
- "/development/frontend/ui/siteHeader-with-breadcrumbs"
+ "/development/frontend/ui/siteHeader-with-breadcrumbs",
+ "/development/frontend/ui/design-settings-menu"
]
}
]