mirror of
https://github.com/navidrome/navidrome.git
synced 2025-07-16 16:41:16 +03:00
* feat: add TimeNow function to SchedulerService plugin Added new TimeNow RPC method to the SchedulerService host service that returns the current time in two formats: RFC3339Nano string and Unix milliseconds int64. This provides plugins with a standardized way to get current time information from the host system. The implementation includes: - TimeNowRequest/TimeNowResponse protobuf message definitions - Go host service implementation using time.Now() - Complete test coverage with format validation - Generated WASM interface code for plugin communication * feat: add LocalTimeZone field to TimeNow response Added LocalTimeZone field to TimeNowResponse message in the SchedulerService plugin host service. This field contains the server's local timezone name (e.g., 'America/New_York', 'UTC') providing plugins with timezone context alongside the existing RFC3339Nano and Unix milliseconds timestamps. The implementation includes: - New local_time_zone protobuf field definition - Go implementation using time.Now().Location().String() - Updated test coverage with timezone validation - Generated protobuf serialization/deserialization code * docs: update plugin README with TimeNow function documentation Updated the plugins README.md to document the new TimeNow function in the SchedulerService. The documentation includes detailed descriptions of the three return formats (RFC3339Nano, UnixMilli, LocalTimeZone), practical use cases, and a comprehensive Go code example showing how plugins can access current time information for logging, calculations, and timezone-aware operations. * docs: remove wrong comment from InitRequest Signed-off-by: Deluan <deluan@navidrome.org> * fix: add missing TimeNow method to namedSchedulerService Added TimeNow method implementation to namedSchedulerService struct to satisfy the scheduler.SchedulerService interface contract. This method was recently added to the interface but the namedSchedulerService wrapper was not updated, causing compilation failures in plugin tests. The implementation is a simple pass-through to the underlying scheduler service since TimeNow doesn't require any special handling for named callbacks. --------- Signed-off-by: Deluan <deluan@navidrome.org>
95 lines
3.4 KiB
Go
95 lines
3.4 KiB
Go
//go:build wasip1
|
|
|
|
package api
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"github.com/navidrome/navidrome/plugins/host/scheduler"
|
|
)
|
|
|
|
var callbacks = make(namedCallbacks)
|
|
|
|
// RegisterNamedSchedulerCallback registers a named scheduler callback. Named callbacks allow multiple callbacks to be registered
|
|
// within the same plugin, and for the schedules to be scoped to the named callback. If you only need a single callback, you can use
|
|
// the default (unnamed) callback registration function, RegisterSchedulerCallback.
|
|
// It returns a scheduler.SchedulerService that can be used to schedule jobs for the named callback.
|
|
//
|
|
// Notes:
|
|
//
|
|
// - You can't mix named and unnamed callbacks within the same plugin.
|
|
// - The name should be unique within the plugin, and it's recommended to use a short, descriptive name.
|
|
// - The name is case-sensitive.
|
|
func RegisterNamedSchedulerCallback(name string, cb SchedulerCallback) scheduler.SchedulerService {
|
|
callbacks[name] = cb
|
|
RegisterSchedulerCallback(&callbacks)
|
|
return &namedSchedulerService{name: name, svc: scheduler.NewSchedulerService()}
|
|
}
|
|
|
|
const zwsp = string('\u200b')
|
|
|
|
// namedCallbacks is a map of named scheduler callbacks. The key is the name of the callback, and the value is the callback itself.
|
|
type namedCallbacks map[string]SchedulerCallback
|
|
|
|
func parseKey(key string) (string, string) {
|
|
parts := strings.SplitN(key, zwsp, 2)
|
|
if len(parts) != 2 {
|
|
return "", ""
|
|
}
|
|
return parts[0], parts[1]
|
|
}
|
|
|
|
func (n *namedCallbacks) OnSchedulerCallback(ctx context.Context, req *SchedulerCallbackRequest) (*SchedulerCallbackResponse, error) {
|
|
name, scheduleId := parseKey(req.ScheduleId)
|
|
cb, exists := callbacks[name]
|
|
if !exists {
|
|
return nil, nil
|
|
}
|
|
req.ScheduleId = scheduleId
|
|
return cb.OnSchedulerCallback(ctx, req)
|
|
}
|
|
|
|
// namedSchedulerService is a wrapper around the host scheduler service that prefixes the schedule IDs with the
|
|
// callback name. It is returned by RegisterNamedSchedulerCallback, and should be used by the plugin to schedule
|
|
// jobs for the named callback.
|
|
type namedSchedulerService struct {
|
|
name string
|
|
cb SchedulerCallback
|
|
svc scheduler.SchedulerService
|
|
}
|
|
|
|
func (n *namedSchedulerService) makeKey(id string) string {
|
|
return n.name + zwsp + id
|
|
}
|
|
|
|
func (n *namedSchedulerService) mapResponse(resp *scheduler.ScheduleResponse, err error) (*scheduler.ScheduleResponse, error) {
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
_, resp.ScheduleId = parseKey(resp.ScheduleId)
|
|
return resp, nil
|
|
}
|
|
|
|
func (n *namedSchedulerService) ScheduleOneTime(ctx context.Context, request *scheduler.ScheduleOneTimeRequest) (*scheduler.ScheduleResponse, error) {
|
|
key := n.makeKey(request.ScheduleId)
|
|
request.ScheduleId = key
|
|
return n.mapResponse(n.svc.ScheduleOneTime(ctx, request))
|
|
}
|
|
|
|
func (n *namedSchedulerService) ScheduleRecurring(ctx context.Context, request *scheduler.ScheduleRecurringRequest) (*scheduler.ScheduleResponse, error) {
|
|
key := n.makeKey(request.ScheduleId)
|
|
request.ScheduleId = key
|
|
return n.mapResponse(n.svc.ScheduleRecurring(ctx, request))
|
|
}
|
|
|
|
func (n *namedSchedulerService) CancelSchedule(ctx context.Context, request *scheduler.CancelRequest) (*scheduler.CancelResponse, error) {
|
|
key := n.makeKey(request.ScheduleId)
|
|
request.ScheduleId = key
|
|
return n.svc.CancelSchedule(ctx, request)
|
|
}
|
|
|
|
func (n *namedSchedulerService) TimeNow(ctx context.Context, request *scheduler.TimeNowRequest) (*scheduler.TimeNowResponse, error) {
|
|
return n.svc.TimeNow(ctx, request)
|
|
}
|