mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-05 23:26:38 +08:00
feat(core): bind request services and implement registered tasks
Wire plugin services through Bind/InjectFrom and AppContext so HTTP and workers resolve dependencies after Apply. Register TaskHandler objects with persisted results, and implement send_email_code, mail:send, cleanup_inactive_users, and dispatch_bot_msg.
This commit is contained in:
@@ -229,6 +229,22 @@ func TestTaskExtension(t *testing.T) {
|
||||
assert.False(t, ok)
|
||||
}
|
||||
|
||||
func TestTaskRegisterRejectsNilHandler(t *testing.T) {
|
||||
tr := extpoints.NewTaskRegistry()
|
||||
assert.Panics(t, func() {
|
||||
tr.Register("broken:task", nil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTaskRegisterRejectsDuplicateType(t *testing.T) {
|
||||
tr := extpoints.NewTaskRegistry()
|
||||
handler := func(ctx context.Context, payload []byte) error { return nil }
|
||||
tr.Register("system:cleanup", handler, extpoints.WithTaskType("system_cleanup"))
|
||||
assert.Panics(t, func() {
|
||||
tr.Register("admin:system_cleanup", handler, extpoints.WithTaskType("system_cleanup"))
|
||||
})
|
||||
}
|
||||
|
||||
func TestScheduleExtension(t *testing.T) {
|
||||
sr := extpoints.NewScheduleRegistry()
|
||||
require.NotNil(t, sr)
|
||||
|
||||
@@ -5,6 +5,8 @@ package extpoints
|
||||
|
||||
import (
|
||||
"Wavelet/core/contracts"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
@@ -230,10 +232,15 @@ func NewTaskRegistry() *TaskRegistry {
|
||||
}
|
||||
|
||||
// Register registers a task pattern and its handler with optional configuration.
|
||||
// A nil handler panics. A non-empty Type that is already used by another pattern panics.
|
||||
func (t *TaskRegistry) Register(pattern string, handler any, opts ...TaskOption) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
if isNilTaskHandler(handler) {
|
||||
panic(fmt.Sprintf("extpoints: nil handler for task pattern %q", pattern))
|
||||
}
|
||||
|
||||
td := TaskDefinition{
|
||||
Pattern: pattern,
|
||||
Handler: handler,
|
||||
@@ -245,8 +252,23 @@ func (t *TaskRegistry) Register(pattern string, handler any, opts ...TaskOption)
|
||||
opt(&td)
|
||||
}
|
||||
}
|
||||
if td.Type == "" {
|
||||
td.Type = pattern
|
||||
}
|
||||
|
||||
if _, exists := t.lookup[pattern]; exists {
|
||||
for _, item := range t.tasks {
|
||||
if item.Pattern == pattern {
|
||||
continue
|
||||
}
|
||||
if item.Type == td.Type {
|
||||
panic(fmt.Sprintf("extpoints: duplicate task type %q (patterns %q and %q)", td.Type, item.Pattern, pattern))
|
||||
}
|
||||
}
|
||||
|
||||
if existing, exists := t.lookup[pattern]; exists {
|
||||
if existing.Type != "" && existing.Type != pattern {
|
||||
delete(t.lookup, existing.Type)
|
||||
}
|
||||
for i, item := range t.tasks {
|
||||
if item.Pattern == pattern {
|
||||
t.tasks[i] = td
|
||||
@@ -258,13 +280,44 @@ func (t *TaskRegistry) Register(pattern string, handler any, opts ...TaskOption)
|
||||
}
|
||||
|
||||
t.lookup[pattern] = td
|
||||
if td.Type != pattern {
|
||||
t.lookup[td.Type] = td
|
||||
}
|
||||
}
|
||||
|
||||
func isNilTaskHandler(handler any) bool {
|
||||
if handler == nil {
|
||||
return true
|
||||
}
|
||||
v := reflect.ValueOf(handler)
|
||||
switch v.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Map, reflect.Pointer, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
|
||||
return v.IsNil()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Unregister removes a registered task definition by its pattern.
|
||||
func (t *TaskRegistry) Unregister(pattern string) bool {
|
||||
return unregisterEntry(&t.mu, t.lookup, &t.tasks, pattern, func(item TaskDefinition) bool {
|
||||
return item.Pattern == pattern
|
||||
})
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
td, ok := t.lookup[pattern]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
delete(t.lookup, td.Pattern)
|
||||
if td.Type != "" && td.Type != td.Pattern {
|
||||
delete(t.lookup, td.Type)
|
||||
}
|
||||
filtered := t.tasks[:0]
|
||||
for _, item := range t.tasks {
|
||||
if item.Pattern != td.Pattern {
|
||||
filtered = append(filtered, item)
|
||||
}
|
||||
}
|
||||
t.tasks = filtered
|
||||
return true
|
||||
}
|
||||
|
||||
// Tasks returns a copy of all registered TaskDefinitions.
|
||||
@@ -280,13 +333,6 @@ func (t *TaskRegistry) Tasks() []TaskDefinition {
|
||||
func (t *TaskRegistry) Get(pattern string) (TaskDefinition, bool) {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
if td, ok := t.lookup[pattern]; ok {
|
||||
return td, true
|
||||
}
|
||||
for _, td := range t.tasks {
|
||||
if td.Type == pattern {
|
||||
return td, true
|
||||
}
|
||||
}
|
||||
return TaskDefinition{}, false
|
||||
td, ok := t.lookup[pattern]
|
||||
return td, ok
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user