Crates.io | hammerwork-web |
lib.rs | hammerwork-web |
version | 1.15.2 |
created_at | 2025-06-30 12:29:38.774959+00 |
updated_at | 2025-08-25 04:26:53.645616+00 |
description | Web-based admin dashboard for Hammerwork job queues with real-time monitoring, webhook management, event streaming, and comprehensive job queue administration |
homepage | https://github.com/CodingAnarchy/hammerwork |
repository | https://github.com/CodingAnarchy/hammerwork |
max_upload_size | |
id | 1731791 |
size | 438,674 |
A modern, real-time web-based admin dashboard for monitoring and managing Hammerwork job queues. Built with Rust, Warp, and WebSockets for high-performance job queue administration.
The dashboard provides:
# Install from crates.io
cargo install hammerwork-web --features postgres
# Or build from source
git clone https://github.com/CodingAnarchy/hammerwork.git
cd hammerwork/hammerwork-web
cargo build --release --features postgres
# Start the dashboard (PostgreSQL)
hammerwork-web --database-url postgresql://user:pass@localhost/hammerwork
# Start with authentication enabled
hammerwork-web \
--database-url postgresql://user:pass@localhost/hammerwork \
--auth \
--username admin \
--password-file /path/to/password_hash.txt
# Start with custom port and CORS enabled
hammerwork-web \
--database-url mysql://user:pass@localhost/hammerwork \
--bind 0.0.0.0 \
--port 9090 \
--cors
Create a dashboard.toml
configuration file:
bind_address = "0.0.0.0"
port = 8080
database_url = "postgresql://localhost/hammerwork"
pool_size = 10
static_dir = "./assets"
enable_cors = false
request_timeout = "30s"
[auth]
enabled = true
username = "admin"
password_hash = "$2b$12$..." # bcrypt hash
session_timeout = "8h"
max_failed_attempts = 5
lockout_duration = "15m"
[websocket]
ping_interval = "30s"
max_connections = 100
message_buffer_size = 1024
max_message_size = 65536
Then start with:
hammerwork-web --config dashboard.toml
Add to your Cargo.toml
:
[dependencies]
hammerwork-web = { version = "1.3", features = ["postgres"] }
# or for MySQL:
# hammerwork-web = { version = "1.3", features = ["mysql"] }
use hammerwork_web::{WebDashboard, DashboardConfig};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = DashboardConfig {
bind_address: "127.0.0.1".to_string(),
port: 8080,
database_url: "postgresql://localhost/hammerwork".to_string(),
pool_size: 5,
static_dir: "./assets".into(),
enable_cors: true,
request_timeout: Duration::from_secs(30),
..Default::default()
};
let dashboard = WebDashboard::new(config).await?;
dashboard.start().await?;
Ok(())
}
use hammerwork_web::{WebDashboard, DashboardConfig, AuthConfig};
let config = DashboardConfig::new()
.with_database_url("postgresql://localhost/hammerwork")
.with_bind_address("0.0.0.0", 8080)
.with_auth("admin", "$2b$12$hash...") // bcrypt hash
.with_cors(true);
let dashboard = WebDashboard::new(config).await?;
dashboard.start().await?;
The dashboard exposes a complete REST API:
All API endpoints (except /health
) require authentication when enabled:
curl -u admin:password http://localhost:8080/api/stats/overview
GET /health
- Health check (no auth required)GET /api/stats/overview
- System overview statisticsGET /api/stats/throughput?period=24h
- Throughput dataGET /api/queues
- List all queues with statisticsPOST /api/queues/{name}/clear
- Clear all jobs from queuePOST /api/queues/{name}/pause
- Pause queue processingPOST /api/queues/{name}/resume
- Resume queue processingGET /api/jobs?status=failed&limit=50
- List jobs with filtersGET /api/jobs/{id}
- Get job detailsPOST /api/jobs
- Create new jobPOST /api/jobs/{id}/retry
- Retry failed jobDELETE /api/jobs/{id}
- Delete jobGET /api/archive/jobs?queue=email&limit=50
- List archived jobs with filtersPOST /api/archive/jobs
- Archive jobs based on configurable policyPOST /api/archive/jobs/{id}/restore
- Restore an archived job to pending statusDELETE /api/archive/purge
- Permanently purge old archived jobsGET /api/archive/stats?queue=email
- Get archive statistics and metricsGET /api/spawn/info
- List available spawn API endpointsGET /api/jobs/{id}/children?include_grandchildren=true
- List spawned child jobsGET /api/jobs/{id}/parent
- Get parent job informationGET /api/jobs/{id}/spawn-tree?format=json&max_depth=5
- Get complete spawn hierarchyGET /api/spawn/operations?limit=50
- List spawn operationsGET /api/spawn/operations/{id}
- Get spawn operation detailsPOST /api/jobs/{id}/spawn
- Manually trigger spawn operationGET /api/spawn/stats?queue=data_processing
- Get spawn operation statisticsConnect to ws://localhost:8080/ws
for real-time updates:
const ws = new WebSocket('ws://localhost:8080/ws');
// Subscribe to events
ws.send(JSON.stringify({
type: 'Subscribe',
event_types: ['queue_updates', 'job_updates', 'system_alerts']
}));
// Handle updates
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('Received:', message);
};
Use the provided scripts to set up test databases:
# Set up both PostgreSQL and MySQL test databases
./scripts/setup-test-databases.sh both
# PostgreSQL only
./scripts/setup-test-databases.sh postgres
# MySQL only
./scripts/setup-test-databases.sh mysql
Default test database connections:
postgresql://postgres:hammerwork@localhost:5433/hammerwork
mysql://root:hammerwork@localhost:3307/hammerwork
# Build with PostgreSQL support
cargo build --features postgres
# Build with MySQL support
cargo build --features mysql
# Build with authentication support
cargo build --features "postgres,auth"
# Build everything
cargo build --all-features
# Unit tests
cargo test
# Integration tests (requires database)
cargo test --features postgres -- --ignored
# Test with both databases
./scripts/setup-test-databases.sh test
# Format code
cargo fmt
# Lint code
cargo clippy --all-features -- -D warnings
# Run with hot reload (requires cargo-watch)
cargo watch -x "run --features postgres -- --database-url postgresql://postgres:hammerwork@localhost:5433/hammerwork"
# Generate documentation
cargo doc --all-features --open
The dashboard frontend is built with vanilla JavaScript, HTML, and CSS for minimal dependencies and fast loading.
assets/
├── index.html # Main dashboard page
├── dashboard.css # Styles and responsive design
├── dashboard.js # WebSocket client and UI logic
└── chart.min.js # Chart.js for data visualization
src/api/
ServerMessage
enum in src/websocket.rs
assets/dashboard.js
and update UI in index.html
tests/
# List archived jobs
curl -u admin:password "http://localhost:8080/api/archive/jobs?queue=email&limit=10"
# Archive completed jobs older than 7 days
curl -u admin:password -X POST http://localhost:8080/api/archive/jobs \
-H "Content-Type: application/json" \
-d '{
"queue_name": "email",
"reason": "automatic",
"archived_by": "scheduler",
"dry_run": false,
"policy": {
"archive_completed_after": 604800000000000,
"compress_payloads": true,
"enabled": true
}
}'
# Restore an archived job
curl -u admin:password -X POST http://localhost:8080/api/archive/jobs/12345/restore \
-H "Content-Type: application/json" \
-d '{"reason": "data recovery", "restored_by": "admin"}'
# Get archive statistics
curl -u admin:password http://localhost:8080/api/archive/stats?queue=email
# Using bcrypt command-line tool
echo -n "your-password" | bcrypt-tool hash
# Or in Rust
use bcrypt::{hash, DEFAULT_COST};
let hash = hash("your-password", DEFAULT_COST)?;
FROM rust:1.70 as builder
WORKDIR /app
COPY . .
RUN cargo build --release --features postgres
FROM debian:booksworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/hammerwork-web /usr/local/bin/
COPY --from=builder /app/hammerwork-web/assets /app/assets
WORKDIR /app
EXPOSE 8080
CMD ["hammerwork-web", "--bind", "0.0.0.0", "--port", "8080"]
[Unit]
Description=Hammerwork Web Dashboard
After=network.target postgresql.service
[Service]
Type=simple
User=hammerwork
WorkingDirectory=/opt/hammerwork
ExecStart=/opt/hammerwork/hammerwork-web --config /etc/hammerwork/dashboard.toml
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
server {
listen 80;
server_name hammerwork.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
pool_size
based on concurrent usersmax_connections
for your use caserequest_timeout
for your network# Enable debug logging
RUST_LOG=hammerwork_web=debug hammerwork-web --config dashboard.toml
# Monitor WebSocket connections
curl http://localhost:8080/api/stats/overview | jq '.websocket_connections'
# Database connection health
curl http://localhost:8080/health
Database Connection Failed
Error: Database connection failed
Static Assets Not Found
Error: Static file not found
static_dir
path in configurationindex.html
Authentication Issues
401 Unauthorized
WebSocket Connection Failed
WebSocket connection closed unexpectedly
# Enable verbose logging
RUST_LOG=debug hammerwork-web --config dashboard.toml
# Enable specific module logging
RUST_LOG=hammerwork_web::websocket=trace hammerwork-web --config dashboard.toml
We welcome contributions! Please see the main CONTRIBUTING.md for guidelines.
This project is licensed under the MIT License - see the LICENSE file for details.
See CHANGELOG.md for version history and changes.