Example #1
0
        public async Task MaterializeAsync(ILogStore store, byte[] secretKey   = default, long?startingFrom = default,
                                           CancellationToken cancellationToken = default)
        {
            if (startingFrom == default)
            {
                startingFrom = Interlocked.Read(ref _index) + 1;
            }

            foreach (var entry in store.StreamEntries((ulong)startingFrom, secretKey))
            {
                Interlocked.Exchange(ref _index, (long)entry.Index.GetValueOrDefault());

                foreach (var @object in entry.Objects)
                {
                    switch (@object.Data)
                    {
                    case Namespace ns:
                    {
                        var key = ns;
                        Namespaces.Add(key);
                        _namespace = key;

                        if (!Revisions.ContainsKey(_namespace.Value))
                        {
                            Revisions.Add(_namespace.Value,
                                          new Dictionary <string, ulong>(StringComparer.OrdinalIgnoreCase));
                        }

                        if (!Manifest.ContainsKey(_namespace.Value))
                        {
                            Manifest.Add(_namespace.Value, new Dictionary <ulong, List <Schema> >());
                        }

                        if (!Roles.ContainsKey(_namespace.Value))
                        {
                            Roles.Add(_namespace.Value, new List <string>());
                        }

                        break;
                    }

                    case Schema schema:
                    {
                        var key = schema.Name;

                        if (!Revisions[_namespace.Value].TryGetValue(key, out var revision))
                        {
                            Revisions[_namespace.Value].Add(key, revision = 1);
                        }

                        if (!Manifest[_namespace.Value].TryGetValue(revision, out var manifest))
                        {
                            Manifest[_namespace.Value].Add(revision, manifest = new List <Schema>());
                        }

                        if (!Schemas.TryGetValue(key, out var schemaMap))
                        {
                            Schemas.Add(key, schemaMap = new Dictionary <ulong, List <Schema> >());
                        }

                        if (!schemaMap.TryGetValue(revision, out var list))
                        {
                            schemaMap.Add(revision, list = new List <Schema>());
                        }

                        manifest.Add(schema);
                        list.Add(schema);

                        await _events.OnSchemaAddedAsync(store, schema, cancellationToken);

                        break;
                    }

                    case RevokeRole revokeRole:
                    {
                        if (!revokeRole.Verify())
                        {
                            throw new InvalidOperationException($"invalid {revokeRole.Type}");
                        }

                        if (RoleGrants.TryGetValue(_namespace.Value, out var lookup) &&
                            lookup.Count == 1 &&
                            lookup[Constants.DefaultOwnerRole].Count == 1)
                        {
                            throw new CannotRemoveSingleOwnerException("cannot revoke admin rights of only owner");
                        }

                        break;
                    }

                    default:
                        throw new NotImplementedException(@object.Data.GetType().Name);
                    }
                }
            }
        }