public ProjectPreview( IProjectLike project, IFileSystem shell, BuildOutputDirGenerator buildOutputDirGenerator, ProxyServer proxy) { Name = project.Name; var simulatorHost = ProjectProcess.SpawnAsync().Replay(1); var simulatorMessages = simulatorHost.Switch(p => p.Messages.RefCount()).Publish().RefCount(); var assemblyBuilt = simulatorMessages.TryParse(AssemblyBuilt.MessageType, AssemblyBuilt.ReadDataFrom); var bytecodeGenerated = simulatorMessages.TryParse(BytecodeGenerated.MessageType, BytecodeGenerated.ReadDataFrom); var bytecodeUpdated = simulatorMessages.TryParse(BytecodeUpdated.MessageType, BytecodeUpdated.ReadDataFrom); _project = project; _buildOutputDirGenerator = buildOutputDirGenerator; _proxy = proxy; _simulatorHost = simulatorHost; _assetsWatcher = new AssetsWatcher(shell, project.RootDirectory, Scheduler.Default); var bytecode = bytecodeGenerated.Select(msg => msg.Bytecode); _coalesceEntryCache = new CoalesceEntryCache(); var assets = project.BundleFiles.CombineLatest(project.FuseJsFiles, (a, b) => a.Concat(b)); var reifyMessages = ReifyProject(bytecode, bytecodeUpdated, _coalesceEntryCache, assets); var dependencyMessages = _assetsWatcher.UpdateChangedDependencies(bytecode.Select(bc => bc.Dependencies.ToImmutableHashSet())); var bundleFileMessages = _assetsWatcher.UpdateChangedBundleFiles(project.BundleFiles); var fuseJsFileMessages = _assetsWatcher.UpdateChangedFuseJsFiles(project.FuseJsFiles); _dispose = Observable.Merge( bundleFileMessages, dependencyMessages, fuseJsFileMessages, reifyMessages) .Subscribe(e => _coalesceEntryCache.Add(e)); var incommingMessages = new Subject <IBinaryMessage>(); var clientAdded = new Subject <string>(); var clientRemoved = new Subject <string>(); var socketServer = SocketServer.Start( port: 0, clientRun: (clientStream, endPoint) => { bool isDisconnected = false; var writeMessages = _coalesceEntryCache .ReplayFrom(-1) .ObserveOn(TaskPoolScheduler.Default) .Subscribe(cacheEntry => { if (isDisconnected) { return; } try { using (var memoryStream = new MemoryStream()) { using (var memoryStreamWriter = new BinaryWriter(memoryStream)) { // ReSharper disable once AccessToDisposedClosure cacheEntry.Entry.BlobData.Do(message => message.WriteTo(memoryStreamWriter)); clientStream.Write(memoryStream.ToArray(), 0, (int)memoryStream.Length); } } } catch (Exception) { isDisconnected = true; } }); var clientInfo = Optional.None <RegisterName>(); try { using (var binaryStream = new BinaryReader(clientStream)) { while (true) { var msg = BinaryMessage.ReadFrom(binaryStream); if (!clientInfo.HasValue) { clientInfo = BinaryMessage.TryParse(msg, RegisterName.MessageType, RegisterName.ReadDataFrom); if (clientInfo.HasValue) { clientAdded.OnNext(clientInfo.Value.DeviceId); } } incommingMessages.OnNext(msg); } } } finally { if (clientInfo.HasValue) { clientRemoved.OnNext(clientInfo.Value.DeviceId); } writeMessages.Dispose(); } }); Assembly = assemblyBuilt; Port = socketServer.LocalEndPoint.Port; Bytecode = bytecodeGenerated; PackageReferences = project.PackageReferences; ProjectReferences = project.ProjectReferences; ClientAdded = clientAdded; ClientRemoved = clientRemoved; Messages = Observable.Merge( incommingMessages, simulatorMessages); AccessCode = CodeGenerator.CreateRandomCode(5); }
public PreviewService() { _shell = new Shell(); _buildOutputDirGenerator = new BuildOutputDirGenerator(_shell); _proxy = ProxyServer.Start(_logMessages.OnNext); }