1
0
mirror of https://github.com/pocketbase/pocketbase.git synced 2024-11-28 10:03:42 +02:00

fixed realtime delete event to be called after the record was deleted from the db

This commit is contained in:
Gani Georgiev 2023-05-29 22:28:07 +03:00
parent 729f9f142e
commit 7de346b532
3 changed files with 62 additions and 12 deletions

View File

@ -21,6 +21,10 @@
- (@todo docs) Changed the After* hooks to be called right before writing the user response, allowing users to return response errors from the after hooks.
- Fixed realtime delete event to be called after the record was deleted from the DB (_including transactions and cascade delete operations_).
- Added `subscriptions.Client.Unset()` helper to remove a single cached item from the client store.
## v0.16.4-WIP

View File

@ -267,7 +267,7 @@ func (api *realtimeApi) bindEvents() {
api.app.OnModelAfterCreate().PreAdd(func(e *core.ModelEvent) error {
if record := api.resolveRecord(e.Model); record != nil {
if err := api.broadcastRecord("create", record); err != nil && api.app.IsDebug() {
if err := api.broadcastRecord("create", record, false); err != nil && api.app.IsDebug() {
log.Println(err)
}
}
@ -276,7 +276,7 @@ func (api *realtimeApi) bindEvents() {
api.app.OnModelAfterUpdate().PreAdd(func(e *core.ModelEvent) error {
if record := api.resolveRecord(e.Model); record != nil {
if err := api.broadcastRecord("update", record); err != nil && api.app.IsDebug() {
if err := api.broadcastRecord("update", record, false); err != nil && api.app.IsDebug() {
log.Println(err)
}
}
@ -285,7 +285,16 @@ func (api *realtimeApi) bindEvents() {
api.app.OnModelBeforeDelete().Add(func(e *core.ModelEvent) error {
if record := api.resolveRecord(e.Model); record != nil {
if err := api.broadcastRecord("delete", record); err != nil && api.app.IsDebug() {
if err := api.broadcastRecord("delete", record, true); err != nil && api.app.IsDebug() {
log.Println(err)
}
}
return nil
})
api.app.OnModelAfterDelete().Add(func(e *core.ModelEvent) error {
if record := api.resolveRecord(e.Model); record != nil {
if err := api.broadcastDryCachedRecord("delete", record); err != nil && api.app.IsDebug() {
log.Println(err)
}
}
@ -367,7 +376,7 @@ type recordData struct {
Record *models.Record `json:"record"`
}
func (api *realtimeApi) broadcastRecord(action string, record *models.Record) error {
func (api *realtimeApi) broadcastRecord(action string, record *models.Record, dryCache bool) error {
collection := record.Collection()
if collection == nil {
return errors.New("Record collection not set.")
@ -399,9 +408,6 @@ func (api *realtimeApi) broadcastRecord(action string, record *models.Record) er
dataBytes, err := json.Marshal(data)
if err != nil {
if api.app.IsDebug() {
log.Println(err)
}
return err
}
@ -438,17 +444,46 @@ func (api *realtimeApi) broadcastRecord(action string, record *models.Record) er
}
}
routine.FireAndForget(func() {
if !client.IsDiscarded() {
client.Channel() <- msg
}
})
if dryCache {
client.Set(action+"/"+data.Record.Id, msg)
} else {
routine.FireAndForget(func() {
if !client.IsDiscarded() {
client.Channel() <- msg
}
})
}
}
}
return nil
}
// broadcastDryCachedRecord broadcasts record if it is cached in the client context.
func (api *realtimeApi) broadcastDryCachedRecord(action string, record *models.Record) error {
clients := api.app.SubscriptionsBroker().Clients()
for _, client := range clients {
key := action + "/" + record.Id
msg, ok := client.Get(key).(subscriptions.Message)
if !ok {
continue
}
client.Unset(key)
client := client
routine.FireAndForget(func() {
if !client.IsDiscarded() {
client.Channel() <- msg
}
})
}
return nil
}
type getter interface {
Get(string) any
}

View File

@ -35,6 +35,9 @@ type Client interface {
// Set stores any value to the client's context.
Set(key string, value any)
// Unset removes a single value from the client's context.
Unset(key string)
// Get retrieves the key value from the client's context.
Get(key string) any
@ -157,6 +160,14 @@ func (c *DefaultClient) Set(key string, value any) {
c.store[key] = value
}
// Unset implements the [Client.Unset] interface method.
func (c *DefaultClient) Unset(key string) {
c.mux.Lock()
defer c.mux.Unlock()
delete(c.store, key)
}
// Discard implements the [Client.Discard] interface method.
func (c *DefaultClient) Discard() {
c.mux.Lock()