Example #1
0
        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);
        }
Example #2
0
 public PreviewService()
 {
     _shell = new Shell();
     _buildOutputDirGenerator = new BuildOutputDirGenerator(_shell);
     _proxy = ProxyServer.Start(_logMessages.OnNext);
 }