As part of using TimescaleDB, which requires a timestamp as the primary key (time in SensorReading), I need to handle the case when the same timestamp is used by different sensor values. One elegant solution might be to smear colliding timestamps (add a microsecond on collision).
How can this problem be solved in a robust and performant manner for the following models?
class Sensor(models.Model):
name = models.CharField(max_length=50)
class SensorReading(models.Model):
time = models.DateTimeField(primary_key=True, default=datetime.now)
sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE)
value = models.FloatField()
P.S. This is a workaround as Django does not support composite primary keys. Otherwise it would be possible to set the sensor and timestamp as a composite primary key.
One solution I found was to use a try/except block around the model save call. Try to add a sensor reading, which will succeed most of the time, but if a collision occurs handle that error. Ensure that the exception thrown is exactly because of that collision and then increment the timestamp by one microsecond (the smallest resolution). Then repeat the try to save the sensor reading. This will almost always succeed due to the low collision probability in the first place. Below is the code tested to recursively handle incrementing the timestamp until it succeeds.
A more robust implementation might also add a max number of tries before aborting.