59 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			59 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """passbook outpost signals"""
 | |
| from asgiref.sync import async_to_sync
 | |
| from channels.layers import get_channel_layer
 | |
| from django.db.models import Model
 | |
| from django.db.models.signals import post_save
 | |
| from django.dispatch import receiver
 | |
| from structlog import get_logger
 | |
| 
 | |
| from passbook.outposts.models import Outpost, OutpostModel
 | |
| 
 | |
| LOGGER = get_logger()
 | |
| 
 | |
| 
 | |
| @receiver(post_save, sender=Outpost)
 | |
| # pylint: disable=unused-argument
 | |
| def ensure_user_and_token(sender, instance, **_):
 | |
|     """Ensure that token is created/updated on save"""
 | |
|     _ = instance.token
 | |
| 
 | |
| 
 | |
| @receiver(post_save)
 | |
| # pylint: disable=unused-argument
 | |
| def post_save_update(sender, instance, **_):
 | |
|     """If an OutpostModel, or a model that is somehow connected to an OutpostModel is saved,
 | |
|     we send a message down the relevant OutpostModels WS connection to trigger an update"""
 | |
|     if isinstance(instance, OutpostModel):
 | |
|         LOGGER.debug("triggering outpost update from outpostmodel", instance=instance)
 | |
|         _send_update(instance)
 | |
|         return
 | |
| 
 | |
|     for field in instance._meta.get_fields():
 | |
|         # Each field is checked if it has a `related_model` attribute (when ForeginKeys or M2Ms)
 | |
|         # are used, and if it has a value
 | |
|         if not hasattr(field, "related_model"):
 | |
|             continue
 | |
|         if not field.related_model:
 | |
|             continue
 | |
|         if not issubclass(field.related_model, OutpostModel):
 | |
|             continue
 | |
| 
 | |
|         field_name = f"{field.name}_set"
 | |
|         if not hasattr(instance, field_name):
 | |
|             continue
 | |
| 
 | |
|         LOGGER.debug("triggering outpost update from from field", field=field.name)
 | |
|         # Because the Outpost Model has an M2M to Provider,
 | |
|         # we have to iterate over the entire QS
 | |
|         for reverse in getattr(instance, field_name).all():
 | |
|             _send_update(reverse)
 | |
| 
 | |
| 
 | |
| def _send_update(outpost_model: Model):
 | |
|     """Send update trigger for each channel of an outpost model"""
 | |
|     for outpost in outpost_model.outpost_set.all():
 | |
|         channel_layer = get_channel_layer()
 | |
|         for channel in outpost.channels:
 | |
|             LOGGER.debug("sending update", channel=channel)
 | |
|             async_to_sync(channel_layer.send)(channel, {"type": "event.update"})
 |