Files
navidrome/plugins/capabilities
Deluan Quintão 668869b6c7 feat(plugins): add TaskQueue host service for persistent background task queues (#5116)
* feat(plugins): define TaskQueue host service interface

Add the TaskQueueService interface with CreateQueue, Enqueue,
GetTaskStatus, and CancelTask methods plus QueueConfig struct.

* feat(plugins): define TaskWorker capability for task execution callbacks

* feat(plugins): add taskqueue permission to manifest schema

Add TaskQueuePermission with maxConcurrency option.

* feat(plugins): implement TaskQueue service with SQLite persistence and workers

Per-plugin SQLite database with queues and tasks tables. Worker goroutines
dequeue tasks and invoke nd_task_execute callback. Exponential backoff
retries, rate limiting via delayMs, automatic cleanup of terminal tasks.

* feat(plugins): require TaskWorker capability for taskqueue permission

* feat(plugins): register TaskQueue host service in manager

* feat(plugins): add test-taskqueue plugin for integration testing

* feat(plugins): add integration tests for TaskQueue host service

* docs: document TaskQueue module for persistent task queues

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(plugins): harden TaskQueue host service with validation and safety improvements

Add input validation (queue name length, payload size limits), extract
status string constants to eliminate raw SQL literals, make CreateQueue
idempotent via upsert for crash recovery, fix RetentionMs default check
for negative values, cap exponential backoff at 1 hour to prevent
overflow, and replace manual mutex-based delay enforcement with
rate.Limiter from golang.org/x/time/rate for correct concurrent worker
serialization.

* refactor(plugins): remove capability check for TaskWorker in TaskQueue host service

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(plugins): use context-aware database execution in TaskQueue host service

Signed-off-by: Deluan <deluan@navidrome.org>

* refactor(plugins): streamline task queue configuration and error handling

Signed-off-by: Deluan <deluan@navidrome.org>

* feat(plugins): increase maxConcurrency for task queue and handle budget exhaustion

Signed-off-by: Deluan <deluan@navidrome.org>

* refactor(plugins): simplify goroutine management in task queue service

Signed-off-by: Deluan <deluan@navidrome.org>

* feat(plugins): update TaskWorker interface to return status messages and refactor task queue service

Signed-off-by: Deluan <deluan@navidrome.org>

* feat(plugins): add ClearQueue function to remove pending tasks from a specified queue

Signed-off-by: Deluan <deluan@navidrome.org>

* refactor(plugins): use migrateDB for task queue schema and fix constant name collision

Replaced the raw db.Exec call in createTaskQueueSchema with migrateDB,
matching the pattern used by createKVStoreSchema. This enables version-tracked
schema migrations via SQLite's PRAGMA user_version, allowing future schema
changes to be appended incrementally. Also renamed cleanupInterval to
taskCleanupInterval to resolve a redeclaration conflict with host_kvstore.go.

* regenerate PDKs

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-03 13:48:49 -05:00
..

Navidrome Plugin Capabilities

This directory contains the Go interface definitions for Navidrome plugin capabilities. These interfaces are the source of truth for plugin development and are used to generate:

  1. Go PDK packages (pdk/go/*/) - Type-safe wrappers for Go plugin developers
  2. Rust PDK crates (pdk/rust/*/) - Type-safe wrappers for Rust plugin developers
  3. XTP YAML schemas (*.yaml) - Schema files for other Extism plugin languages (TypeScript, Python, C#, Zig, C++, ...)

For Go Plugin Developers

Go developers should use the generated PDK packages in plugins/pdk/go/. See the example Go plugins in plugins/examples/ for usage patterns.

For Rust Plugin Developers

Rust developers should use the generated PDK crate in plugins/pdk/rust/nd-pdk. See the example Rust plugins in plugins/examples for usage patterns.

For Non-Go Plugin Developers

If you're developing plugins in other languages (TypeScript, Rust, Python, C#, Zig, C++), you can use the XTP CLI to generate type-safe bindings from the YAML schema files in this directory.

Prerequisites

Install the XTP CLI:

# macOS
brew install dylibso/tap/xtp

# Other platforms - see https://docs.xtp.dylibso.com/docs/cli
curl https://static.dylibso.com/cli/install.sh | bash

Generating Plugin Scaffolding

Use the XTP CLI to generate plugin boilerplate from any capability schema:

# TypeScript
xtp plugin init --schema-file plugins/capabilities/metadata_agent.yaml \
    --template typescript --path my-plugin

# Rust
xtp plugin init --schema-file plugins/capabilities/scrobbler.yaml \
    --template rust --path my-plugin

# Python
xtp plugin init --schema-file plugins/capabilities/lifecycle.yaml \
    --template python --path my-plugin

# C#
xtp plugin init --schema-file plugins/capabilities/scheduler_callback.yaml \
    --template csharp --path my-plugin

# Go (alternative to using the PDK packages)
xtp plugin init --schema-file plugins/capabilities/websocket_callback.yaml \
    --template go --path my-plugin

Available Capabilities

Capability Schema File Description
Metadata Agent metadata_agent.yaml Fetch artist biographies, album images, and similar artists
Scrobbler scrobbler.yaml Report listening activity to external services
Lifecycle lifecycle.yaml Plugin initialization callbacks
Scheduler Callback scheduler_callback.yaml Scheduled task execution
WebSocket Callback websocket_callback.yaml Real-time WebSocket message handling

Building Your Plugin

After generating the scaffolding, implement the required functions and build your plugin as a WebAssembly module. The exact build process depends on your chosen language - see the Extism PDK documentation for language-specific guides.

XTP Schema Generation

The YAML schemas in this package are automatically generated from the capability Go interfaces using ndpgen. To regenerate the schemas after modifying the interfaces, run:

cd plugins/cmd/ndpgen && go run . -schemas -input=./plugins/capabilities

Resources