I have an item repository which is used from both view-model (main thread) and a background service (background thread). Both can query the item repository and update items.
class ItemRepository
{
Item GetItem(int id);
void UpdateItem(Item item);
}
public class Item
{
ItemState State { get; set; }
}
// Component A (view-model)
// Runs on main thread
void ExecuteUpdateItemCommand()
{
var item = _itemRepo.GetItem(1);
if(item.State == ItemState.First)
{
itemState.State = ItemState.Second;
_itemRepo.UpdateItem(item); // Ideally this should be on a separate thread but for now lets' assume it's on main thread
}
}
// Component B (background service - receives notifications from backedn)
// Runs on a background thread
void OnNotificationReceived()
{
var item = _itemRepo.GetItem(1);
if(item.State == ItemState.First)
{
item.State = GetNextState(); // some busines logic specific to Component B
_itemRepo.UpdateItem(item);
}
}
The issue I have is with implementing synchronization of item query and update across the two threads.
Without synchronization, the state of item can become corrupt, because after the if statement returns on one thread, the other thread might be updating the item state to another value, which could break the business logic of the item state.
A simple solution is to just have the Component A and Component B lock on same shared object. From a design perspective, how to share this object across components (each with different purpose) ?
Another solution I see is to have a service which does both the business logic of component A and component B just for the sake of synchronizing the calls, but that's not a good solution in my opinion.
I am looking for better implementations than these.
My feeling is a good solution might be one which allows me to run things on a context. Something like
ItemSyncContext.Run(ExecuteUpdateItemCommand);
and
ItemSyncContext.Run(OnNotificationReceived);