I have some tables of temporal data, for example:
- DeviceHealthEvent: DeviceId, Signal, Hourmeter, EventDate, LastChangedDate
- DeviceStateEvent: DeviceId, StateID, TimeCategory, TimeSubCategory, EventDate, LastChangedDate
- DevicePositionEvent: DeviceId, East, North, Altitude, Speed, Direction, EventDate, LastChangedDate
- DeviceUserEvent: DeviceId, UserID, ShiftID, EventDate, LastChangedDate
So, as we can see, a device has a lot of information being stored in different tables and these tables grow a lot and are constantly changing.
To avoid having to go to each table and search for the current device record, I thought of creating a table with all the latest information from Device:
- DeviceRealTime: DeviceId, Signal, Hourmeter, StateID, TimeCategory, TimeSubCategory, East, North, Altitude, Speed, Direction, UserID, ShiftID, LastChangedDate
This table will have a cache and each item of this cache refer to a device, I thought about updating this cache by subscribing to an event called AfterCommited of each temporal table.
To persist the cache of DeviceRealTime items in the database table I created a reminder that goes through the cache and updates the table.
Implementation:
public class DeviceRealtimeRepo: IDeviceRealtimeRepo<DeviceRealTime>
{
private ConcurrentDictionary<int, DeviceRealTime> _cache;
public DeviceRealtimeRepo()
{
DeviceHealthEventRepo.AfterCommited + = OnDeviceHealthEventAfterCommited();
DevicePositionEventRepo.AfterCommited + = OnDevicePositionEventAfterCommited();
DeviceUserEventRepo.AfterCommited + = OnDeviceUserEventAfterCommited();
CreateReminder();
}
public DeviceRealTime GetItem(int id)
{
return GetOrCreate(id);
}
// Creates a Timer (and a BackgroundWorker) to call the OnExecuteReminder method every 30 seconds
private CreateReminder()
{
}
// callback that will update the DeviceRealTime table based on the _cache
private OnExecuteReminder()
{
}
// update the cache item after a commit in the DeviceHealthEvent is done
private void OnDeviceHealthEventAfterCommited(Action action, DeviceHealthEvent newtem, DeviceHealthEvent oldItem)
{
// how to discard a delayed item to keep the cache in the correct state???
if (action == Actions.Add || action == Actions.Update)
{
DeviceRealTime cachedItem = GetOrCreate(newtem.DeviceId);
cachedItem.Signal = newtem.Signal;
cachedItem.Hourmeter = newtem.Hourmeter;
cachedItem.LastChangedDate = DateTime.UtcNow();
}
else if (action == Actions.Delete)
{
TryRemove(newtem.DeviceId);
}
}
private DeviceRealTime GetOrCreate(int deviceId)
{
DeviceRealTime cachedItem;
if (!_cache.TryGetValue(deviceId, out cachedItem))
{
cachedItem = createItem();
// Save data in cache
_cache[deviceId] = cachedItem;
}
return cachedItem;
}
}
Well, in summary, I haven't figured out a way to discard delay events of AfterCommited. For example, OnDeviceHealthEventAfterCommited is executed but the newItem is already overdue.
I don't know if there is an architectural desing that addresses this requirement.
Aucun commentaire:
Enregistrer un commentaire