fixed realtime delete event to be called after the record was deleted from the db
This commit is contained in:
		
							parent
							
								
									729f9f142e
								
							
						
					
					
						commit
						7de346b532
					
				|  | @ -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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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,6 +444,9 @@ func (api *realtimeApi) broadcastRecord(action string, record *models.Record) er | |||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			if dryCache { | ||||
| 				client.Set(action+"/"+data.Record.Id, msg) | ||||
| 			} else { | ||||
| 				routine.FireAndForget(func() { | ||||
| 					if !client.IsDiscarded() { | ||||
| 						client.Channel() <- msg | ||||
|  | @ -445,10 +454,36 @@ func (api *realtimeApi) broadcastRecord(action string, record *models.Record) er | |||
| 				}) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	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 | ||||
| } | ||||
|  |  | |||
|  | @ -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() | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue