QueueUpdater.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. using InABox.Clients;
  2. using InABox.Core;
  3. namespace InABox.Avalonia;
  4. public class QueueUpdaterState
  5. {
  6. public Guid ID { get; set; }
  7. public string OriginalState { get; set; }
  8. public Dictionary<string,object> Changes { get; set; } = new();
  9. public bool DisableUpdates { get; set; }
  10. }
  11. public class QueueUpdater<TEntity> : IDisposable, IQueueUpdater<TEntity>
  12. where TEntity : Entity, IPersistent, IRemotable, new()
  13. {
  14. private static String StateFile(Guid id) => $"{id}.{typeof(TEntity).Name.Split('.').Last()}";
  15. private Dictionary<TEntity, QueueUpdaterState> _cache = new();
  16. private string _path;
  17. private IModelHost _host;
  18. public QueueUpdater(IModelHost host, string path)
  19. {
  20. _host = host;
  21. _path = path;
  22. LoadCache();
  23. _host.AddUpdateQueue(this);
  24. }
  25. public void Add(TEntity entity)
  26. {
  27. var _state = new QueueUpdaterState();
  28. _state.ID = Guid.NewGuid();
  29. _state.OriginalState = Serialization.Serialize(entity);
  30. Save(_state);
  31. _cache[entity] = _state;
  32. entity.PropertyChanged += (sender, args) =>
  33. {
  34. var state = _cache[entity];
  35. state.Changes[args.PropertyName] = CoreUtils.GetPropertyValue(entity,args.PropertyName);
  36. Save(state);
  37. };
  38. }
  39. public void Update(TEntity entity, Action<TEntity> action)
  40. {
  41. var state = _cache[entity];
  42. state.DisableUpdates = true;
  43. action(entity);
  44. Save(state);
  45. state.DisableUpdates = false;
  46. }
  47. private void Save(QueueUpdaterState state)
  48. {
  49. var _text = Serialization.Serialize(state);
  50. File.WriteAllText(StateFile(state.ID), _text);
  51. }
  52. public TEntity[] Items => _cache.Keys.ToArray();
  53. private void LoadCache()
  54. {
  55. _cache.Clear();
  56. var files = Directory.GetFiles(_path, $"*.{typeof(TEntity).Name.Split('.').Last()}");
  57. foreach (var file in files)
  58. {
  59. if (!Guid.TryParse(Path.GetFileNameWithoutExtension(file), out Guid id))
  60. continue;
  61. var _text = File.ReadAllText(file);
  62. if (string.IsNullOrWhiteSpace(_text))
  63. continue;
  64. var _state = Serialization.Deserialize<QueueUpdaterState>(_text);
  65. if (_state == null)
  66. continue;
  67. var _entity = Serialization.Deserialize<TEntity>(_state.OriginalState);
  68. if (_entity == null)
  69. continue;
  70. foreach (var change in _state.Changes)
  71. CoreUtils.SetPropertyValue(_entity,change.Key,change.Value);
  72. _cache[_entity] = _state;
  73. }
  74. }
  75. public void ProcessQueue()
  76. {
  77. var item = Items.FirstOrDefault();
  78. if (item != null)
  79. {
  80. if (item.IsChanged() && _host.Status == ConnectionStatus.Connected)
  81. {
  82. new Client<TEntity>().Save(item, "Updated from Mobile Device");
  83. var state = Serialization.Serialize(item);
  84. File.WriteAllText(StateFile(_cache[item].ID),state);
  85. }
  86. }
  87. }
  88. public void Dispose()
  89. {
  90. _host.RemoveUpdateQueue(this);
  91. }
  92. }