SkillAgentSearch skills...

Sasquatch

No description available

Install / Use

/learn @crowdwave/Sasquatch
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Sasquatch Message Queue

A lightweight, SQS-compatible message queue service backed by SQLite. Single binary, zero external dependencies beyond the database file.

Quick Start

# Run with file-backed storage
./sasquatch --port 8080

# Run with in-memory storage (data lost on restart)
./sasquatch --memory --port 8080

Command Line Options

| Flag | Default | Description | |------|---------|-------------| | --port | 8080 | Port to listen on | | --host | localhost | Host to bind to | | --memory | false | Use in-memory SQLite (no persistence) | | --max-queue-length | 5000 | Maximum messages per queue | | --max-message-size | 256 | Maximum message size in KB (max: 10240) | | --version | | Print version and exit | | --help | | Print help and exit | | --config | | Path to .ini configuration file | | --generate-config | | Print a sample .ini config to stdout and exit |

CLI flags override config file values. Config file values override built-in defaults.


Configuration File

All tuneable system parameters can be set via an .ini file. Generate a sample with all defaults:

./sasquatch --generate-config > sasquatch.ini

Then start with it:

./sasquatch --config sasquatch.ini

Config Reference

[server]
port = 8080                          # 1-65535
host = localhost
memory = false                       # true/false/yes/no/1/0

[queue]
max_queue_length = 5000              # >= 1
max_message_size_kb = 256            # 1-10240
max_request_body_size_kb = 1024      # >= 1
default_visibility_timeout = 30      # 0-43200 seconds
default_max_receives = 4             # >= 1
poison_max_receives = 100            # >= default_max_receives
default_retention_period = 345600    # 60-1209600 seconds (4 days default)
default_wait_time_seconds = 20       # 0-20
default_dedup_time_period = 300      # 1-43200 seconds (5 min default)
default_priority = 100               # >= 0

[cleanup]
poison_cleanup_interval = 60         # seconds, >= 1
retention_cleanup_interval = 600     # seconds, >= 1
dedup_cleanup_interval = 60          # seconds, >= 1

[database]
reader_pool_size = 4                 # 1-64

The config file is validated on startup. If any value is out of range, an unknown key is present, or a duplicate key is found, the service prints all errors and exits with a non-zero status. Section headers are optional — all keys are matched by name regardless of section.


API Reference

All endpoints enforce HTTP methods (POST or GET as documented). Requests with the wrong method receive a 405 Method Not Allowed response.

All POST endpoints accept and return JSON. All errors are returned as:

{
  "error": {
    "code": "ErrorCode",
    "message": "Human-readable description"
  }
}

Internal errors return a generic message to clients. Details are logged server-side only.

POST /send

Send a message to a queue. Queues are created implicitly on first message.

Request:

{
  "queue_name": "my-queue",
  "message_body": "Hello, world!",
  "priority": 100,
  "delay_seconds": 0,
  "message_retention_period": 345600,
  "message_deduplication_id": "abc123",
  "message_deduplication_time_period": 300,
  "message_attributes": {
    "content_type": "application/json",
    "correlation_id": "req-12345"
  }
}

| Field | Required | Default | Description | |-------|----------|---------|-------------| | queue_name | Yes | | Alphanumeric, hyphens, underscores | | message_body | Yes | | Message content string (up to max-message-size) | | priority | No | 100 | Higher = dequeued first (0–1000). Explicit 0 is respected | | delay_seconds | No | 0 | Seconds before message becomes visible (0–43200) | | message_retention_period | No | 345600 (4 days) | Seconds before auto-deletion (60–1209600) | | message_deduplication_id | No | | Alphanumeric, max 128 chars. Rejects duplicates within the time period | | message_deduplication_time_period | No | 300 (5 min) | Seconds the dedup ID is enforced (max 43200) | | message_attributes | No | | Key-value metadata (max 10 keys, key max 64 chars, value max 1024 chars) |

Response (200):

{
  "message_id": "550e8400-e29b-41d4-a716-446655440000",
  "md5_of_message_body": "65a8e27d8879283831b664bd8b7f0ad4",
  "sequence_number": 42
}

Error codes: ValidationError (400), QueueFull (503), MessageSizeExceeded (413), DuplicateMessage (409)


POST /send_batch

Send up to 10 messages in a single request. Each message is validated independently — one bad message does not prevent the others from being sent. All successful messages are inserted in a single transaction (one fsync instead of 10).

Request:

{
  "messages": [
    {"queue_name": "orders", "message_body": "order-1", "priority": 100},
    {"queue_name": "orders", "message_body": "order-2", "priority": 50, "message_attributes": {"source": "web"}},
    {"queue_name": "alerts", "message_body": "disk-full", "priority": 200}
  ]
}

| Field | Required | Description | |-------|----------|-------------| | messages | Yes | Array of 1–10 SendRequest objects (same fields as /send) |

Response (200):

{
  "successful": [
    {"index": 0, "message_id": "...", "md5_of_message_body": "...", "sequence_number": 1},
    {"index": 2, "message_id": "...", "md5_of_message_body": "...", "sequence_number": 1}
  ],
  "failed": [
    {"index": 1, "error": {"code": "DuplicateMessage", "message": "..."}}
  ]
}

The index field corresponds to the position in the input messages array. Messages can be sent to different queues in the same batch. Queue length is checked once per queue and cached across the batch.


POST /receive

Receive one or more messages with long polling. Messages become invisible to other consumers for the duration of the visibility timeout. If not deleted within that window, they become visible again.

Request:

{
  "queue_name": "my-queue",
  "visibility_timeout": 30,
  "wait_time_seconds": 20,
  "max_number_of_messages": 1,
  "max_receives": 4,
  "dead_letter_queue_name": "my-queue-dlq",
  "peek": false,
  "shuffle": false
}

| Field | Required | Default | Description | |-------|----------|---------|-------------| | queue_name | Yes | | Queue to receive from | | visibility_timeout | No | 30 | Seconds message is hidden after receive (0–43200). Explicit 0 means message stays visible after receive | | wait_time_seconds | No | 20 | Long-poll duration if no messages available (0–20). Explicit 0 disables long-polling (returns immediately) | | max_number_of_messages | No | 1 | Number of messages to receive (1–10) | | max_receives | No | 4 | Max times a message can be received before poison handling (1–10) | | dead_letter_queue_name | No | | Queue to move poison messages to (must differ from queue_name) | | peek | No | false | Read-only mode: returns the next message without changing visibility, receive count, or issuing a receipt handle | | shuffle | No | false | Return a random visible message instead of priority/FIFO order |

Response (200):

{
  "messages": [
    {
      "message_id": "550e8400-e29b-41d4-a716-446655440000",
      "receipt_handle": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "message_body": "Hello, world!",
      "md5_of_message_body": "65a8e27d8879283831b664bd8b7f0ad4",
      "priority": 100,
      "approximate_receive_count": 1,
      "approximate_first_receive_timestamp": 1700000000,
      "sent_timestamp": 1700000000,
      "sequence_number": 42,
      "message_attributes": {
        "content_type": "application/json",
        "correlation_id": "req-12345"
      }
    }
  ]
}

If no messages are available after the wait time, returns {"messages": []}.

Peek Mode

When peek is true, the message is returned read-only — no visibility change, no receive count increment, no receipt handle. The message remains visible to other consumers. Peek always returns at most one message (repeated peeks return the same message). Cannot be combined with dead_letter_queue_name.

Shuffle Mode

When shuffle is true, a random visible message is selected instead of following priority/FIFO ordering. Can be combined with peek for a random read-only sample. Works normally with visibility semantics when peek is false.


POST /delete

Delete one or more messages by receipt handle. Call this after successfully processing a message.

Request:

{
  "receipt_handles": ["7c9e6679-7425-40de-944b-e07fc1f90ae7"]
}

| Field | Required | Description | |-------|----------|-------------| | receipt_handles | Yes | Array of UUIDs (1–10) |

Response (200):

{
  "deleted": 1
}

Error codes: NotFound (404) if no messages matched

Deduplication note: Messages sent with a message_deduplication_id are soft-deleted — the body is cleared but the row remains until the deduplication time period expires, preventing the same dedup ID from being reused.


POST /change_visibility

Change the visibility timeout of messages by receipt handle. Affects messages regardless of whether they are currently in-flight or have become visible again, as long as the receipt handle matches (a re-received message gets a new receipt handle, so stale handles naturally stop matching).

Request:

{
  "receipt_handles": ["7c9e6679-7425-40de-944b-e07fc1f90ae7"],
  "visibility_timeout": 60
}

| Field | Required | Description | |-------|----------|-------------| | receipt_handles | Yes | Array of UUIDs (1–10) | | visibility_timeout | Yes | New timeout in seconds from now (-43200 to 43200) |

A negative value makes the message visible immediately (releases it back to the queue).

Response (200):

{
  "result": "ok"
}

POST /delete_all

Purge all messages from a queue.

Request:

{
  "queue_name": "my-queue"
}
View on GitHub
GitHub Stars4
CategoryDevelopment
Updated1mo ago
Forks0

Languages

Go

Security Score

80/100

Audited on Feb 28, 2026

No findings