Monitoring ExecutionsPreview
Check Execution Status
Use the tailorctl workspace workflow get-execution command to check the status of a workflow execution:
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workflow</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">get-execution</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--execution-id</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy</span></span>
<span></span>
Output:
Execution ID: yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
Workflow ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Status: success
Started At: 2025-01-15T10:30:00Z
Finished At: 2025-01-15T10:30:45Z
Job Executions:
1. main (success)
Started: 2025-01-15T10:30:00Z
Finished: 2025-01-15T10:30:45Z
Stacked Task: main
2. fetchData (success)
Started: 2025-01-15T10:30:05Z
Finished: 2025-01-15T10:30:15Z
Stacked Task: main/fetchData
3. processData (success)
Started: 2025-01-15T10:30:20Z
Finished: 2025-01-15T10:30:40Z
Stacked Task: main/processData
Result: {
"success": true,
"processed": {...}
}
Execution Status
A workflow execution can have the following statuses:
- pending: Waiting to be picked up by the scheduler
- pending_resume: Waiting to be resumed after a failure
- running: Currently executing
- success: Completed successfully
- failed: Execution failed (can be resumed)
Follow Execution Progress
You can follow an execution in real-time using the --follow flag:
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workflow</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">get-execution</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--execution-id</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--follow</span></span>
<span></span>
This will poll for updates until the execution completes.
The start command returns an execution ID that you can use with get-execution to monitor progress.
Monitoring in Tailor Console
You can also monitor workflow executions through the Tailor Console web interface.
The console provides:
- Visual execution timeline
- Job function execution details
- Error messages and logs
- Execution history for all workflow runs
Resume and Retry
Resuming Failed Workflows
If a workflow execution fails, you can resume it from the point of failure using the resume command:
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workflow</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">resume</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--execution-id</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy</span></span>
<span></span>
What happens during resume:
- The system retrieves all successful job function results from the previous run
- The workflow restarts from the main function
- Successful job functions are skipped (their cached results are used)
- Failed or not-yet-executed job functions are executed
Example:
Original execution:
fetchData → Success ✓
processData → Success ✓
saveToDb → Failed ✗
After resume:
fetchData → Skipped (cached)
processData → Skipped (cached)
saveToDb → Executed again
When to Use Resume
Resume is useful when:
- External API calls fail temporarily
- Database connections time out
- Rate limits are hit
- Any transient error occurs
Important: Only resume when the failure is transient. If the failure is due to invalid data or logic errors, fix the issue and create a new execution instead.
Idempotency Best Practices
Design your job functions to be idempotent (safe to execute multiple times):
Good - Idempotent:
<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">async</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">function</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">main</span><span style="color: var(--shiki-color-text)">(args) {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)">// Check if record already exists</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">existing</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">await</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">checkRecord</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-constant)">args</span><span style="color: var(--shiki-color-text)">.id);</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">if</span><span style="color: var(--shiki-color-text)"> (existing) {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">console</span><span style="color: var(--shiki-token-function)">.log</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">"Record already exists, skipping"</span><span style="color: var(--shiki-color-text)">);</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">return</span><span style="color: var(--shiki-color-text)"> existing;</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)">// Create only if not exists</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">return</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">await</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">createRecord</span><span style="color: var(--shiki-color-text)">(args);</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Avoid - Not Idempotent:
<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">function</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">main</span><span style="color: var(--shiki-color-text)">(args) {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)">// This will create duplicate records on retry</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">return</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">createRecord</span><span style="color: var(--shiki-color-text)">(args);</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Tips for idempotency:
- Check for existing records before creating
- Use unique identifiers (UUIDs, order IDs, etc.)
- Design operations to be repeatable
- Use database constraints to prevent duplicates
Testing and Development
For rapid prototyping and local testing, you can use tailorctl commands to manage workflows without writing Terraform/CUE configurations. These commands are designed for quick iteration during development.
Important: These commands are intended for testing and development purposes only. For production deployments, always use Terraform or CUE with proper version control and Infrastructure as Code practices.
Quick Workflow Creation
The tailorctl workspace workflow create command provides a fast way to create workflows by automatically analyzing dependencies:
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workflow</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">create</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--workflow-name</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">my-test-workflow</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--workflow-script-path</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">./main.js</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--workflow-deps-dir</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">./deps</span></span>
<span></span>
How it works:
- Analyzes your main script for
tailor.workflow.triggerJobFunction()calls - Automatically creates job functions for all dependencies
- Detects circular dependencies and missing functions
- Creates the workflow with all required function mappings
- Always uses the latest versions of job functions
Example output:
✓ Analyzing dependencies...
✓ Found dependencies: fetchData, processData, saveData
✓ Creating job function: fetchData (version 1)
✓ Creating job function: processData (version 1)
✓ Creating job function: saveData (version 1)
✓ Creating job function: main (version 1)
✓ Creating workflow: my-test-workflow
Workflow ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Command Options
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workflow</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">create</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--workflow-name</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)"><</span><span style="color: var(--shiki-token-string)">nam</span><span style="color: var(--shiki-color-text)">e</span><span style="color: var(--shiki-token-keyword)">></span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)"># Required: Workflow name</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">--workflow-script-path</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)"><</span><span style="color: var(--shiki-token-string)">pat</span><span style="color: var(--shiki-color-text)">h</span><span style="color: var(--shiki-token-keyword)">></span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)"># Required: Path to main script</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">--workflow-deps-dir</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)"><</span><span style="color: var(--shiki-token-string)">di</span><span style="color: var(--shiki-color-text)">r</span><span style="color: var(--shiki-token-keyword)">></span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)"># Optional: Directory with dependencies</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">--quiet</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)"># Optional: Suppress output</span></span>
<span></span>
When to Use tailorctl Commands
Recommended for:
- Local development: Quick iteration on workflow logic
- Prototyping: Testing ideas before formalizing in Terraform/CUE
- Debugging: Troubleshooting workflow behavior
- Learning: Understanding workflow concepts and patterns
- Ad-hoc testing: One-off experiments
Not recommended for:
- Production deployments: No version control or audit trail
- Team collaboration: Changes are not tracked in source control
- Complex version management: Always uses latest versions
- CI/CD pipelines: Not suitable for automated deployments
- Compliance requirements: Lacks Infrastructure as Code guarantees