/// <summary>
        /// Creates a new app and a master fork
        /// On success sets the app id
        /// </summary>
        /// <param name="appId"></param>
        /// <param name="name"></param>
        /// <param name="description"></param>
        public void CreateApp(int appId, string name, string description)
        {
            var        bytesAppIds = KeyValueStore.Get(KeyValueStore.DefaultType, KeyGenerator.AppsKey, null);
            List <int> appIds      = null;

            if (bytesAppIds != null)
            {
                appIds = (List <int>)BinarySerializerHelper.DeserializeObject(bytesAppIds);
            }
            else
            {
                appIds = new List <int>();
                KeyValueStore.Set(KeyValueStore.DefaultType, KeyGenerator.AppsKey, BinarySerializerHelper.SerializeObject(appIds), null);
            }

            if (appIds.Contains(appId))
            {
                throw new ArgumentException(nameof(appId));
            }

            appIds.Add(appId);

            KeyValueStore.Set(KeyValueStore.DefaultType, KeyGenerator.AppsKey, BinarySerializerHelper.SerializeObject(appIds), null);

            var res = new App
            {
                Id          = appId,
                Name        = name,
                Description = description
            };

            KeyValueStore.Set(KeyValueStore.DefaultType, KeyGenerator.GenerateAppKey(appId), ProtoBufSerializerHelper.Serialize(res), null);
            KeyValueStore.Set(KeyValueStore.DefaultType, KeyGenerator.GenerateForksKey(appId), BinarySerializerHelper.SerializeObject(new List <int>()), null);

            SetApp(appId);

            CreateMasterFork();
        }
        private void InitForksDict()
        {
            var rawForks = new Dictionary <int, ForkRawData>();
            var forkIds  = (List <int>)BinarySerializerHelper.DeserializeObject(Store.Get(Store.DefaultType, KeyGenerator.GenerateForksKey(AppId), null));

            foreach (var forkId in forkIds)
            {
                rawForks[forkId]         = ProtoBufSerializerHelper.Deserialize <ForkRawData>(Store.Get(Store.DefaultType, KeyGenerator.GenerateForkKey(AppId, forkId), null));
                _forksTimeStamps[forkId] = (DateTime)BinarySerializerHelper.DeserializeObject(Store.Get(Store.DefaultType, KeyGenerator.GenerateForkTimeStampKey(AppId, forkId), null));
            }

            var masterForks = rawForks.Where(x => x.Value.ParentId == 0).Select(x => x.Key).ToArray();

            foreach (var masterFork in masterForks)
            {
                CreateFork(rawForks, masterFork);
            }
        }
        private void UpdateForks()
        {
            var changedForkIds = new HashSet <int>();

            var updatedForkIds = (List <int>)BinarySerializerHelper.DeserializeObject(Store.Get(Store.DefaultType, KeyGenerator.GenerateForksKey(AppId), null));
            var newForkIds     = updatedForkIds.Except(_forks.Keys);

            foreach (var newForkId in newForkIds)
            {
                var bytesNewRawFork = Store.Get(Store.DefaultType, KeyGenerator.GenerateForkKey(AppId, newForkId), null);
                if (bytesNewRawFork == null)
                {
                    continue;
                }

                var newRawFork = ProtoBufSerializerHelper.Deserialize <ForkRawData>(bytesNewRawFork);

                var bytesNewForkTimeStamp = Store.Get(Store.DefaultType, KeyGenerator.GenerateForkTimeStampKey(AppId, newForkId), null);
                if (bytesNewForkTimeStamp == null)
                {
                    continue;
                }

                var newForkTimeStamp = (DateTime)BinarySerializerHelper.DeserializeObject(bytesNewForkTimeStamp);

                var parentFork = newRawFork.ParentId == 0 ? null : _forks[newRawFork.ParentId];
                var newFork    = new Fork
                {
                    Id              = newForkId,
                    Name            = newRawFork.Name,
                    Description     = newRawFork.Description,
                    IsInGracePeriod = newRawFork.IsInGracePeriod,
                    Parent          = parentFork
                };

                if (parentFork != null)
                {
                    parentFork.Children.Add(newFork);
                    changedForkIds.Add(parentFork.Id);
                }

                _forks[newForkId]           = newFork;
                _forksTimeStamps[newForkId] = newForkTimeStamp;
            }
            var toDel = _forks.Keys.Except(updatedForkIds).ToList();

            foreach (var toDelFork in toDel)
            {
                _forks.Remove(toDelFork);
                _forksTimeStamps.Remove(toDelFork);
            }

            foreach (var forkId in _forks.Keys.ToList())
            {
                var newTimeStamp          = (DateTime)BinarySerializerHelper.DeserializeObject(Store.Get(Store.DefaultType, KeyGenerator.GenerateForkTimeStampKey(AppId, forkId), null));
                var _currentForkTimeStamp = _forksTimeStamps[forkId];
                if (newTimeStamp > _currentForkTimeStamp)
                {
                    var rawFork = ProtoBufSerializerHelper.Deserialize <ForkRawData>(Store.Get(Store.DefaultType, KeyGenerator.GenerateForkKey(AppId, forkId), null));
                    _forksTimeStamps[forkId] = newTimeStamp;

                    UpdateFork(_forks[forkId], rawFork);
                    changedForkIds.Add(forkId);
                }
            }

            RaiseForkChanged(changedForkIds.ToList());
        }
 private void SetForkIds(List <int> forkIds)
 {
     KeyValueStore.Set(KeyValueStore.DefaultType, KeyGenerator.GenerateForksKey(AppId), BinarySerializerHelper.SerializeObject(forkIds), null);
 }
 private List <int> GetForkIds()
 {
     return((List <int>)BinarySerializerHelper.DeserializeObject(KeyValueStore.Get(KeyValueStore.DefaultType, KeyGenerator.GenerateForksKey(AppId), null)));
 }