mirror of
https://github.com/navidrome/navidrome.git
synced 2026-05-03 06:51:16 +00:00
feat(scheduler): add Scheduler service interface with host function wrappers for scheduling tasks
This commit is contained in:
parent
c059db4c9c
commit
44c69de525
129
plugins/host/go/nd_host_scheduler.go
Normal file
129
plugins/host/go/nd_host_scheduler.go
Normal file
@ -0,0 +1,129 @@
|
||||
// Code generated by hostgen. DO NOT EDIT.
|
||||
//
|
||||
// This file contains client wrappers for the Scheduler host service.
|
||||
// It is intended for use in Navidrome plugins built with TinyGo.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
)
|
||||
|
||||
// scheduler_scheduleonetime is the host function provided by Navidrome.
|
||||
//
|
||||
//go:wasmimport extism:host/user scheduler_scheduleonetime
|
||||
func scheduler_scheduleonetime(int32, uint64, uint64) uint64
|
||||
|
||||
// scheduler_schedulerecurring is the host function provided by Navidrome.
|
||||
//
|
||||
//go:wasmimport extism:host/user scheduler_schedulerecurring
|
||||
func scheduler_schedulerecurring(uint64, uint64, uint64) uint64
|
||||
|
||||
// scheduler_cancelschedule is the host function provided by Navidrome.
|
||||
//
|
||||
//go:wasmimport extism:host/user scheduler_cancelschedule
|
||||
func scheduler_cancelschedule(uint64) uint64
|
||||
|
||||
// SchedulerScheduleOneTimeResponse is the response type for Scheduler.ScheduleOneTime.
|
||||
type SchedulerScheduleOneTimeResponse struct {
|
||||
NewScheduleID string `json:"newScheduleID,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// SchedulerScheduleRecurringResponse is the response type for Scheduler.ScheduleRecurring.
|
||||
type SchedulerScheduleRecurringResponse struct {
|
||||
NewScheduleID string `json:"newScheduleID,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// SchedulerScheduleOneTime calls the scheduler_scheduleonetime host function.
|
||||
// ScheduleOneTime schedules a one-time event to be triggered after the specified delay.
|
||||
//
|
||||
// Parameters:
|
||||
// - delaySeconds: Number of seconds to wait before triggering the event
|
||||
// - payload: Data to be passed to the scheduled event handler
|
||||
// - scheduleID: Optional unique identifier for the scheduled job. If empty, one will be generated
|
||||
//
|
||||
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
||||
func SchedulerScheduleOneTime(delaySeconds int32, payload []byte, scheduleID string) (*SchedulerScheduleOneTimeResponse, error) {
|
||||
payloadMem := pdk.AllocateBytes(payload)
|
||||
defer payloadMem.Free()
|
||||
scheduleIDMem := pdk.AllocateString(scheduleID)
|
||||
defer scheduleIDMem.Free()
|
||||
|
||||
// Call the host function
|
||||
responsePtr := scheduler_scheduleonetime(delaySeconds, payloadMem.Offset(), scheduleIDMem.Offset())
|
||||
|
||||
// Read the response from memory
|
||||
responseMem := pdk.FindMemory(responsePtr)
|
||||
responseBytes := responseMem.ReadBytes()
|
||||
|
||||
// Parse the response
|
||||
var response SchedulerScheduleOneTimeResponse
|
||||
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
// SchedulerScheduleRecurring calls the scheduler_schedulerecurring host function.
|
||||
// ScheduleRecurring schedules a recurring event using a cron expression.
|
||||
//
|
||||
// Parameters:
|
||||
// - cronExpression: Standard cron format expression (e.g., "0 0 * * *" for daily at midnight)
|
||||
// - payload: Data to be passed to each scheduled event handler invocation
|
||||
// - scheduleID: Optional unique identifier for the scheduled job. If empty, one will be generated
|
||||
//
|
||||
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
||||
func SchedulerScheduleRecurring(cronExpression string, payload []byte, scheduleID string) (*SchedulerScheduleRecurringResponse, error) {
|
||||
cronExpressionMem := pdk.AllocateString(cronExpression)
|
||||
defer cronExpressionMem.Free()
|
||||
payloadMem := pdk.AllocateBytes(payload)
|
||||
defer payloadMem.Free()
|
||||
scheduleIDMem := pdk.AllocateString(scheduleID)
|
||||
defer scheduleIDMem.Free()
|
||||
|
||||
// Call the host function
|
||||
responsePtr := scheduler_schedulerecurring(cronExpressionMem.Offset(), payloadMem.Offset(), scheduleIDMem.Offset())
|
||||
|
||||
// Read the response from memory
|
||||
responseMem := pdk.FindMemory(responsePtr)
|
||||
responseBytes := responseMem.ReadBytes()
|
||||
|
||||
// Parse the response
|
||||
var response SchedulerScheduleRecurringResponse
|
||||
if err := json.Unmarshal(responseBytes, &response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
// SchedulerCancelSchedule calls the scheduler_cancelschedule host function.
|
||||
// CancelSchedule cancels a scheduled job identified by its schedule ID.
|
||||
//
|
||||
// This works for both one-time and recurring schedules. Once cancelled, the job will not trigger
|
||||
// any future events.
|
||||
//
|
||||
// Returns an error if the schedule ID is not found or if cancellation fails.
|
||||
func SchedulerCancelSchedule(scheduelID string) error {
|
||||
scheduelIDMem := pdk.AllocateString(scheduelID)
|
||||
defer scheduelIDMem.Free()
|
||||
|
||||
// Call the host function
|
||||
responsePtr := scheduler_cancelschedule(scheduelIDMem.Offset())
|
||||
|
||||
// Read the response from memory
|
||||
responseMem := pdk.FindMemory(responsePtr)
|
||||
errStr := string(responseMem.ReadBytes())
|
||||
|
||||
if errStr != "" {
|
||||
return errors.New(errStr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
42
plugins/host/scheduler.go
Normal file
42
plugins/host/scheduler.go
Normal file
@ -0,0 +1,42 @@
|
||||
package host
|
||||
|
||||
import "context"
|
||||
|
||||
// SchedulerService provides task scheduling capabilities for plugins.
|
||||
//
|
||||
// This service allows plugins to schedule both one-time and recurring tasks using
|
||||
// cron expressions. All scheduled tasks can be cancelled using their schedule ID.
|
||||
//
|
||||
//nd:hostservice name=Scheduler permission=scheduler
|
||||
type SchedulerService interface {
|
||||
// ScheduleOneTime schedules a one-time event to be triggered after the specified delay.
|
||||
//
|
||||
// Parameters:
|
||||
// - delaySeconds: Number of seconds to wait before triggering the event
|
||||
// - payload: Data to be passed to the scheduled event handler
|
||||
// - scheduleID: Optional unique identifier for the scheduled job. If empty, one will be generated
|
||||
//
|
||||
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
||||
//nd:hostfunc
|
||||
ScheduleOneTime(ctx context.Context, delaySeconds int32, payload []byte, scheduleID string) (newScheduleID string, err error)
|
||||
|
||||
// ScheduleRecurring schedules a recurring event using a cron expression.
|
||||
//
|
||||
// Parameters:
|
||||
// - cronExpression: Standard cron format expression (e.g., "0 0 * * *" for daily at midnight)
|
||||
// - payload: Data to be passed to each scheduled event handler invocation
|
||||
// - scheduleID: Optional unique identifier for the scheduled job. If empty, one will be generated
|
||||
//
|
||||
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
|
||||
//nd:hostfunc
|
||||
ScheduleRecurring(ctx context.Context, cronExpression string, payload []byte, scheduleID string) (newScheduleID string, err error)
|
||||
|
||||
// CancelSchedule cancels a scheduled job identified by its schedule ID.
|
||||
//
|
||||
// This works for both one-time and recurring schedules. Once cancelled, the job will not trigger
|
||||
// any future events.
|
||||
//
|
||||
// Returns an error if the schedule ID is not found or if cancellation fails.
|
||||
//nd:hostfunc
|
||||
CancelSchedule(ctx context.Context, scheduelID string) error
|
||||
}
|
||||
153
plugins/host/scheduler_gen.go
Normal file
153
plugins/host/scheduler_gen.go
Normal file
@ -0,0 +1,153 @@
|
||||
// Code generated by hostgen. DO NOT EDIT.
|
||||
|
||||
package host
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
extism "github.com/extism/go-sdk"
|
||||
)
|
||||
|
||||
// SchedulerScheduleOneTimeResponse is the response type for Scheduler.ScheduleOneTime.
|
||||
type SchedulerScheduleOneTimeResponse struct {
|
||||
NewScheduleID string `json:"newScheduleID,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// SchedulerScheduleRecurringResponse is the response type for Scheduler.ScheduleRecurring.
|
||||
type SchedulerScheduleRecurringResponse struct {
|
||||
NewScheduleID string `json:"newScheduleID,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// RegisterSchedulerHostFunctions registers Scheduler service host functions.
|
||||
// The returned host functions should be added to the plugin's configuration.
|
||||
func RegisterSchedulerHostFunctions(service SchedulerService) []extism.HostFunction {
|
||||
return []extism.HostFunction{
|
||||
newSchedulerScheduleOneTimeHostFunction(service),
|
||||
newSchedulerScheduleRecurringHostFunction(service),
|
||||
newSchedulerCancelScheduleHostFunction(service),
|
||||
}
|
||||
}
|
||||
|
||||
func newSchedulerScheduleOneTimeHostFunction(service SchedulerService) extism.HostFunction {
|
||||
return extism.NewHostFunctionWithStack(
|
||||
"scheduler_scheduleonetime",
|
||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||
// Read parameters from stack
|
||||
delaySeconds := extism.DecodeI32(stack[0])
|
||||
payload, err := p.ReadBytes(stack[1])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
scheduleID, err := p.ReadString(stack[2])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Call the service method
|
||||
newscheduleid, err := service.ScheduleOneTime(ctx, delaySeconds, payload, scheduleID)
|
||||
if err != nil {
|
||||
schedulerWriteError(p, stack, err)
|
||||
return
|
||||
}
|
||||
// Write JSON response to plugin memory
|
||||
resp := SchedulerScheduleOneTimeResponse{
|
||||
NewScheduleID: newscheduleid,
|
||||
}
|
||||
schedulerWriteResponse(p, stack, resp)
|
||||
},
|
||||
[]extism.ValueType{extism.ValueTypeI32, extism.ValueTypePTR, extism.ValueTypePTR},
|
||||
[]extism.ValueType{extism.ValueTypePTR},
|
||||
)
|
||||
}
|
||||
|
||||
func newSchedulerScheduleRecurringHostFunction(service SchedulerService) extism.HostFunction {
|
||||
return extism.NewHostFunctionWithStack(
|
||||
"scheduler_schedulerecurring",
|
||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||
// Read parameters from stack
|
||||
cronExpression, err := p.ReadString(stack[0])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
payload, err := p.ReadBytes(stack[1])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
scheduleID, err := p.ReadString(stack[2])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Call the service method
|
||||
newscheduleid, err := service.ScheduleRecurring(ctx, cronExpression, payload, scheduleID)
|
||||
if err != nil {
|
||||
schedulerWriteError(p, stack, err)
|
||||
return
|
||||
}
|
||||
// Write JSON response to plugin memory
|
||||
resp := SchedulerScheduleRecurringResponse{
|
||||
NewScheduleID: newscheduleid,
|
||||
}
|
||||
schedulerWriteResponse(p, stack, resp)
|
||||
},
|
||||
[]extism.ValueType{extism.ValueTypePTR, extism.ValueTypePTR, extism.ValueTypePTR},
|
||||
[]extism.ValueType{extism.ValueTypePTR},
|
||||
)
|
||||
}
|
||||
|
||||
func newSchedulerCancelScheduleHostFunction(service SchedulerService) extism.HostFunction {
|
||||
return extism.NewHostFunctionWithStack(
|
||||
"scheduler_cancelschedule",
|
||||
func(ctx context.Context, p *extism.CurrentPlugin, stack []uint64) {
|
||||
// Read parameters from stack
|
||||
scheduelID, err := p.ReadString(stack[0])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Call the service method
|
||||
err = service.CancelSchedule(ctx, scheduelID)
|
||||
if err != nil {
|
||||
// Write error string to plugin memory
|
||||
if ptr, err := p.WriteString(err.Error()); err == nil {
|
||||
stack[0] = ptr
|
||||
}
|
||||
return
|
||||
}
|
||||
// Write empty string to indicate success
|
||||
if ptr, err := p.WriteString(""); err == nil {
|
||||
stack[0] = ptr
|
||||
}
|
||||
},
|
||||
[]extism.ValueType{extism.ValueTypePTR},
|
||||
[]extism.ValueType{extism.ValueTypePTR},
|
||||
)
|
||||
}
|
||||
|
||||
// schedulerWriteResponse writes a JSON response to plugin memory.
|
||||
func schedulerWriteResponse(p *extism.CurrentPlugin, stack []uint64, resp any) {
|
||||
respBytes, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
schedulerWriteError(p, stack, err)
|
||||
return
|
||||
}
|
||||
respPtr, err := p.WriteBytes(respBytes)
|
||||
if err != nil {
|
||||
stack[0] = 0
|
||||
return
|
||||
}
|
||||
stack[0] = respPtr
|
||||
}
|
||||
|
||||
// schedulerWriteError writes an error response to plugin memory.
|
||||
func schedulerWriteError(p *extism.CurrentPlugin, stack []uint64, err error) {
|
||||
errResp := struct {
|
||||
Error string `json:"error"`
|
||||
}{Error: err.Error()}
|
||||
respBytes, _ := json.Marshal(errResp)
|
||||
respPtr, _ := p.WriteBytes(respBytes)
|
||||
stack[0] = respPtr
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user