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. | - (@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 | ## v0.16.4-WIP | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -267,7 +267,7 @@ func (api *realtimeApi) bindEvents() { | ||||||
| 
 | 
 | ||||||
| 	api.app.OnModelAfterCreate().PreAdd(func(e *core.ModelEvent) error { | 	api.app.OnModelAfterCreate().PreAdd(func(e *core.ModelEvent) error { | ||||||
| 		if record := api.resolveRecord(e.Model); record != nil { | 		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) | 				log.Println(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -276,7 +276,7 @@ func (api *realtimeApi) bindEvents() { | ||||||
| 
 | 
 | ||||||
| 	api.app.OnModelAfterUpdate().PreAdd(func(e *core.ModelEvent) error { | 	api.app.OnModelAfterUpdate().PreAdd(func(e *core.ModelEvent) error { | ||||||
| 		if record := api.resolveRecord(e.Model); record != nil { | 		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) | 				log.Println(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -285,7 +285,16 @@ func (api *realtimeApi) bindEvents() { | ||||||
| 
 | 
 | ||||||
| 	api.app.OnModelBeforeDelete().Add(func(e *core.ModelEvent) error { | 	api.app.OnModelBeforeDelete().Add(func(e *core.ModelEvent) error { | ||||||
| 		if record := api.resolveRecord(e.Model); record != nil { | 		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) | 				log.Println(err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -367,7 +376,7 @@ type recordData struct { | ||||||
| 	Record *models.Record `json:"record"` | 	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() | 	collection := record.Collection() | ||||||
| 	if collection == nil { | 	if collection == nil { | ||||||
| 		return errors.New("Record collection not set.") | 		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) | 	dataBytes, err := json.Marshal(data) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if api.app.IsDebug() { |  | ||||||
| 			log.Println(err) |  | ||||||
| 		} |  | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -438,17 +444,46 @@ func (api *realtimeApi) broadcastRecord(action string, record *models.Record) er | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			routine.FireAndForget(func() { | 			if dryCache { | ||||||
| 				if !client.IsDiscarded() { | 				client.Set(action+"/"+data.Record.Id, msg) | ||||||
| 					client.Channel() <- msg | 			} else { | ||||||
| 				} | 				routine.FireAndForget(func() { | ||||||
| 			}) | 					if !client.IsDiscarded() { | ||||||
|  | 						client.Channel() <- msg | ||||||
|  | 					} | ||||||
|  | 				}) | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return nil | 	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 { | type getter interface { | ||||||
| 	Get(string) any | 	Get(string) any | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -35,6 +35,9 @@ type Client interface { | ||||||
| 	// Set stores any value to the client's context.
 | 	// Set stores any value to the client's context.
 | ||||||
| 	Set(key string, value any) | 	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 retrieves the key value from the client's context.
 | ||||||
| 	Get(key string) any | 	Get(key string) any | ||||||
| 
 | 
 | ||||||
|  | @ -157,6 +160,14 @@ func (c *DefaultClient) Set(key string, value any) { | ||||||
| 	c.store[key] = value | 	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.
 | // Discard implements the [Client.Discard] interface method.
 | ||||||
| func (c *DefaultClient) Discard() { | func (c *DefaultClient) Discard() { | ||||||
| 	c.mux.Lock() | 	c.mux.Lock() | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue