1
0
mirror of https://github.com/pocketbase/pocketbase.git synced 2025-04-14 21:11:52 +02:00

[#590] fixed realtime events bind order by adding hooks.PreAdd

This commit is contained in:
Gani Georgiev 2022-09-21 14:41:20 +03:00
parent 9a8c9dd115
commit 954067860c
4 changed files with 40 additions and 13 deletions

View File

@ -166,7 +166,7 @@ func (api *realtimeApi) bindEvents() {
adminTable := (&models.Admin{}).TableName() adminTable := (&models.Admin{}).TableName()
// update user/admin auth state // update user/admin auth state
api.app.OnModelAfterUpdate().Add(func(e *core.ModelEvent) error { api.app.OnModelAfterUpdate().PreAdd(func(e *core.ModelEvent) error {
modelTable := e.Model.TableName() modelTable := e.Model.TableName()
var contextKey string var contextKey string
@ -190,7 +190,7 @@ func (api *realtimeApi) bindEvents() {
}) })
// remove user/admin client(s) // remove user/admin client(s)
api.app.OnModelAfterDelete().Add(func(e *core.ModelEvent) error { api.app.OnModelAfterDelete().PreAdd(func(e *core.ModelEvent) error {
modelTable := e.Model.TableName() modelTable := e.Model.TableName()
var contextKey string var contextKey string
@ -213,14 +213,14 @@ func (api *realtimeApi) bindEvents() {
return nil return nil
}) })
api.app.OnModelAfterCreate().Add(func(e *core.ModelEvent) error { api.app.OnModelAfterCreate().PreAdd(func(e *core.ModelEvent) error {
if record, ok := e.Model.(*models.Record); ok { if record, ok := e.Model.(*models.Record); ok {
api.broadcastRecord("create", record) api.broadcastRecord("create", record)
} }
return nil return nil
}) })
api.app.OnModelAfterUpdate().Add(func(e *core.ModelEvent) error { api.app.OnModelAfterUpdate().PreAdd(func(e *core.ModelEvent) error {
if record, ok := e.Model.(*models.Record); ok { if record, ok := e.Model.(*models.Record); ok {
api.broadcastRecord("update", record) api.broadcastRecord("update", record)
} }

View File

@ -716,7 +716,7 @@ func (app *BaseApp) initLogsDB() error {
return connectErr return connectErr
} }
app.logsDao = app.createDao(app.logsDB) app.logsDao = daos.New(app.logsDB)
return nil return nil
} }
@ -740,12 +740,12 @@ func (app *BaseApp) initDataDB() error {
} }
} }
app.dao = app.createDao(app.db) app.dao = app.createDaoWithHooks(app.db)
return nil return nil
} }
func (app *BaseApp) createDao(db dbx.Builder) *daos.Dao { func (app *BaseApp) createDaoWithHooks(db dbx.Builder) *daos.Dao {
dao := daos.New(db) dao := daos.New(db)
dao.BeforeCreateFunc = func(eventDao *daos.Dao, m models.Model) error { dao.BeforeCreateFunc = func(eventDao *daos.Dao, m models.Model) error {

View File

@ -17,7 +17,18 @@ type Hook[T any] struct {
handlers []Handler[T] handlers []Handler[T]
} }
// Add registers a new handler to the hook. // PreAdd registers a new handler to the hook by prepending it to the existing queue.
func (h *Hook[T]) PreAdd(fn Handler[T]) {
h.mux.Lock()
defer h.mux.Unlock()
// minimize allocations by shifting the slice
h.handlers = append(h.handlers, nil)
copy(h.handlers[1:], h.handlers)
h.handlers[0] = fn
}
// Add registers a new handler to the hook by appending it to the existing queue.
func (h *Hook[T]) Add(fn Handler[T]) { func (h *Hook[T]) Add(fn Handler[T]) {
h.mux.Lock() h.mux.Lock()
defer h.mux.Unlock() defer h.mux.Unlock()

View File

@ -5,18 +5,34 @@ import (
"testing" "testing"
) )
func TestAdd(t *testing.T) { func TestAddAndPreAdd(t *testing.T) {
h := Hook[int]{} h := Hook[int]{}
if total := len(h.handlers); total != 0 { if total := len(h.handlers); total != 0 {
t.Fatalf("Expected no handlers, found %d", total) t.Fatalf("Expected no handlers, found %d", total)
} }
h.Add(func(data int) error { return nil }) triggerSequence := ""
h.Add(func(data int) error { return nil })
if total := len(h.handlers); total != 2 { f1 := func(data int) error { triggerSequence += "f1"; return nil }
t.Fatalf("Expected 2 handlers, found %d", total) f2 := func(data int) error { triggerSequence += "f2"; return nil }
f3 := func(data int) error { triggerSequence += "f3"; return nil }
f4 := func(data int) error { triggerSequence += "f4"; return nil }
h.Add(f1)
h.Add(f2)
h.PreAdd(f3)
h.PreAdd(f4)
h.Trigger(1)
if total := len(h.handlers); total != 4 {
t.Fatalf("Expected %d handlers, found %d", 4, total)
}
expectedTriggerSequence := "f4f3f1f2"
if triggerSequence != expectedTriggerSequence {
t.Fatalf("Expected trigger sequence %s, got %s", expectedTriggerSequence, triggerSequence)
} }
} }