async Task <SAFENetworkContext> RequireContextAsync(RootName root, string apiKey = null) { if (root == null) { throw new ArgumentNullException(nameof(root)); } if (!_contextCache.TryGetValue(root, out SAFENetworkContext result)) { var(stream, store) = await DbFactory.GetDriveDbsAsync(root, apiKey, _secretKey); _sequenceNr = new SequenceNr(); var localState = new Memory.MemoryGateway(); var driveCache = new Memory.SAFENetworkDriveCache(store, localState); var network = new SAFENetworkEventService(stream, store, _secretKey); var materializer = new DriveMaterializer(root, localState, _sequenceNr); var conflictHandler = new VersionConflictHandler(network, materializer); var driveWriter = new DriveWriter(root, driveCache, _sequenceNr); var dbName = Utils.Scrambler.Obfuscate(root.Value, _secretKey); var transactor = new EventTransactor(driveWriter, new DiskWALTransactor(dbName, conflictHandler.Upload), _secretKey); _contextCache.Add(root, result = new SAFENetworkContext(transactor, new DriveReader(driveCache))); var _ = driveCache.GetDrive(root, apiKey, _parameters); // needs to be loaded // We need to wait for all events in local WAL to have been persisted to network // before we materialize new events from network. transactor.Start(_cancellation); // start uploading to network while (DiskWALTransactor.AnyInQueue(dbName)) // wait until queue is empty { await Task.Delay(500); // beware, this will - currently - spin eternally if there is an unresolved version conflict } // (todo: should load snapshot + all events since) var allEvents = network.LoadAsync(fromVersion: 0); // load all events from network (since we don't store it locally) var isMaterialized = await materializer.Materialize(allEvents); // recreate the filesystem locally in memory if (!isMaterialized) { throw new InvalidDataException("Could not materialize network filesystem!"); } } return(result); }
public SAFENetworkContext(EventTransactor writer, DriveReader reader) { Writer = writer; Reader = reader; }