Best Practices
This guide provides comprehensive best practices for using Merobox effectively, from workflow design to testing integration and performance optimization.
Workflow Design
1. Start Simple
Begin with basic workflows and gradually add complexity:
# Start with simple workflows
description: Simple workflow
name: Basic Workflow
nodes:
chain_id: testnet-1
count: 1
image: ghcr.io/calimero-network/merod:edge
steps:
- name: Basic Step
type: script
script: echo "Hello, Merobox!"
stop_all_nodes: true
2. Modular Steps
Break complex operations into smaller, focused steps:
# Good: Modular approach
steps:
- name: Setup Environment
type: script
script: |
echo "Setting up environment..."
# Setup logic
- name: Install Application
type: install_application
node: calimero-node-1
path: ./my-app.wasm
- name: Configure Application
type: script
script: |
echo "Configuring application..."
# Configuration logic
- name: Test Application
type: call
node: calimero-node-1
method: test_functionality
3. Clear Naming
Use descriptive names for steps and variables:
# Good: Descriptive names
steps:
- name: Install User Management Application
type: install_application
node: calimero-node-1
path: ./user-mgmt.wasm
outputs:
user_app_id: applicationId
- name: Create User Management Context
type: create_context
node: calimero-node-1
application_id: '{{user_app_id}}'
outputs:
user_context_id: contextId
admin_key: memberPublicKey
4. Error Handling
Include validation and error checking steps:
steps:
- name: Risky Operation
type: call
node: calimero-node-1
method: risky_method
retry:
attempts: 3
delay: 5
backoff: exponential
on_error:
- name: Log Error
type: script
script: echo "Operation failed: {{error}}"
- name: Cleanup
type: script
script: echo "Cleaning up..."
- name: Validate Results
type: assert
statements:
- '{{result}} != null'
- "contains({{result}}, 'expected_value')"
Testing Integration
1. Isolated Tests
Use separate node prefixes for different test suites:
# Use different prefixes for isolation
@pytest.fixture
def unit_test_cluster():
with cluster(count=1, prefix="unit") as env:
yield env
@pytest.fixture
def integration_test_cluster():
with cluster(count=3, prefix="integration") as env:
yield env
@pytest.fixture
def performance_test_cluster():
with cluster(count=5, prefix="performance") as env:
yield env
2. Resource Cleanup
Always clean up resources after tests:
@pytest.fixture
def test_cluster():
with cluster(count=2, prefix="test") as env:
try:
yield env
finally:
# Cleanup logic
print("Cleaning up test resources...")
3. Parallel Testing
Use different prefixes for parallel test execution:
# Enable parallel testing
pytestmark = pytest.mark.parallel
def test_parallel_1():
with cluster(count=1, prefix="parallel-1") as env:
# Test logic
pass
def test_parallel_2():
with cluster(count=1, prefix="parallel-2") as env:
# Test logic
pass
4. Environment Setup
Use workflows for complex test environment setup:
# workflows/test-setup.yml
description: Test environment setup
name: Test Setup
nodes:
chain_id: testnet-1
count: 3
image: ghcr.io/calimero-network/merod:edge
prefix: test-node
steps:
- name: Install Application
type: install_application
node: test-node-1
path: ./test-app.wasm
dev: true
outputs:
app_id: applicationId
- name: Create Context
type: create_context
node: test-node-1
application_id: '{{app_id}}'
outputs:
context_id: contextId
member_key: memberPublicKey
- name: Setup Test Data
type: call
node: test-node-1
context_id: '{{context_id}}'
executor_public_key: '{{member_key}}'
method: setup_test_data
args:
test_cases: 100
stop_all_nodes: false # Keep nodes running for tests
Performance Considerations
1. Minimal Waits
Use appropriate wait times, not excessive delays:
# Good: Minimal wait times
steps:
- name: Wait for Node
type: wait
seconds: 5 # Reasonable wait time
message: 'Waiting for node to start...'
# Bad: Excessive wait times
steps:
- name: Wait for Node
type: wait
seconds: 300 # Too long!
2. Resource Management
Stop nodes when not needed:
# Good: Stop nodes when done
stop_all_nodes: true
# Or stop specific nodes
steps:
- name: Stop Unused Nodes
type: script
script: |
merobox stop calimero-node-2
merobox stop calimero-node-3
3. Efficient Operations
Design workflows to minimize sequential dependencies:
# Good: Parallel operations
steps:
- name: Parallel Setup
type: parallel
steps:
- name: Setup Node 1
type: script
script: echo "Setting up node 1"
- name: Setup Node 2
type: script
script: echo "Setting up node 2"
- name: Setup Node 3
type: script
script: echo "Setting up node 3"
# Bad: Sequential operations
steps:
- name: Setup Node 1
type: script
script: echo "Setting up node 1"
- name: Setup Node 2
type: script
script: echo "Setting up node 2"
- name: Setup Node 3
type: script
script: echo "Setting up node 3"
4. Monitoring
Include health checks and monitoring in long-running workflows:
steps:
- name: Health Check
type: script
script: |
echo "Checking node health..."
curl -f http://calimero-node-1:2428/health
echo "Node is healthy"
- name: Monitor Performance
type: script
script: |
echo "Monitoring performance..."
# Add monitoring logic
Security Best Practices
1. Use Non-Root Users
nodes:
security:
user: '1000:1000' # Non-root user
read_only: true
no_new_privileges: true
2. Drop Unnecessary Capabilities
nodes:
security:
capabilities:
drop: ['ALL']
add: ['NET_BIND_SERVICE'] # Only add what's needed
3. Use Secrets Management
secrets:
- name: api-key
environment: API_KEY
required: true
nodes:
secrets:
- api-key
environment:
API_KEY_FILE: /run/secrets/api-key
4. Network Segmentation
networks:
- name: calimero-internal
driver: bridge
options:
com.docker.network.bridge.enable_icc: 'false'
com.docker.network.bridge.enable_ip_masquerade: 'true'
Configuration Management
1. Environment-Specific Configuration
# Use different configurations for different environments
development:
nodes:
count: 1
resources:
memory: '1G'
cpus: '0.5'
security:
read_only: false
production:
nodes:
count: 5
resources:
memory: '4G'
cpus: '2.0'
security:
read_only: true
no_new_privileges: true
2. Version Control
Track configuration changes in version control:
# Track workflow files
git add workflows/
git commit -m "Add new workflow configuration"
# Track environment files
git add .env.example
git commit -m "Update environment configuration"
3. Configuration Validation
Validate configuration before deployment:
steps:
- name: Validate Configuration
type: script
script: |
echo "Validating configuration..."
# Add validation logic
echo "Configuration is valid"
Monitoring and Observability
1. Comprehensive Monitoring
monitoring:
enabled: true
metrics:
- cpu_usage
- memory_usage
- disk_usage
- network_io
- application_metrics
alerts:
- metric: memory_usage
threshold: 80
action: restart_node
2. Logging
Include comprehensive logging:
steps:
- name: Log Important Events
type: script
script: |
echo "Starting important operation..."
# Operation logic
echo "Operation completed successfully"
3. Health Checks
Include health checks in workflows:
steps:
- name: Health Check
type: script
script: |
echo "Performing health check..."
curl -f http://calimero-node-1:2428/health
echo "Health check passed"
Troubleshooting
1. Debug Mode
Enable debug mode for troubleshooting:
# Enable debug logging
export LOG_LEVEL=DEBUG
# Run with verbose output
merobox bootstrap run workflow.yml --verbose
2. Resource Monitoring
Monitor resource usage:
# Check resource usage
docker stats $(docker ps -q --filter "name=calimero-")
# Check logs
merobox logs calimero-node-1
3. Network Diagnostics
Diagnose network issues:
# Check network connectivity
docker network ls
docker network inspect calimero-web
# Test connectivity
docker exec calimero-node-1 ping calimero-node-2
Documentation
1. Document Workflows
Include comprehensive documentation:
description: |
This workflow demonstrates how to set up a multi-node
Calimero cluster with authentication service integration.
It includes error handling, monitoring, and cleanup.
name: Multi-Node Auth Setup
# ... workflow steps
2. Document Configuration
Document configuration options:
# Configuration documentation
nodes:
# Number of nodes to create
count: 3
# Docker image to use
image: ghcr.io/calimero-network/merod:edge
# Resource limits
resources:
memory: '2G' # Memory limit per node
cpus: '1.0' # CPU limit per node
3. Document Dependencies
Document external dependencies:
# External dependencies
# - Docker must be running
# - Ports 2428, 2528, 2628 must be available
# - At least 4GB RAM and 2 CPU cores recommended
Common Pitfalls
1. Resource Exhaustion
Problem: Not enough resources for the workload.
Solution: Monitor resource usage and scale appropriately.
# Monitor resources
monitoring:
enabled: true
metrics:
- memory_usage
- cpu_usage
alerts:
- metric: memory_usage
threshold: 80
action: scale_up
2. Network Issues
Problem: Nodes can't communicate with each other.
Solution: Check network configuration and connectivity.
# Proper network configuration
networks:
- name: calimero-web
driver: bridge
options:
com.docker.network.bridge.enable_icc: 'true'
3. Timing Issues
Problem: Operations fail due to timing issues.
Solution: Use appropriate wait times and retry logic.
# Proper timing
steps:
- name: Wait for Node
type: wait
seconds: 10
message: 'Waiting for node to start...'
- name: Retry Operation
type: call
node: calimero-node-1
method: operation
retry:
attempts: 3
delay: 5
Next Steps
Now that you understand best practices:
- Quick Start Tutorials - Get started with Merobox
- Real-World Examples - Practical examples for common scenarios
- Testing Integration Examples - Integration with testing frameworks
- Advanced Examples - Complex workflows and advanced features