コード例 #1
0
ファイル: ProjectPreview.cs プロジェクト: yongaru/fuse-studio
        IObservable <CoalesceEntry> ReifyProject(IObservable <ProjectBytecode> bytecode, IObservable <BytecodeUpdated> bytecodeUpdated, CoalesceEntryCache cache, IObservable <IEnumerable <AbsoluteFilePath> > assets)
        {
            int idx             = 0;
            var bytecodeUpdates = bytecodeUpdated.Select(m => m.ToCoalesceEntry(BytecodeUpdated.MessageType + (++idx)))
                                  .Publish()
                                  .RefCount();

            var clearOldUpdates = bytecodeUpdates
                                  .Buffer(bytecode)
                                  .Select(
                oldUpdates =>
            {
                var cachedUpdates = new List <CoalesceEntry>();
                foreach (var oldUpdate in oldUpdates)
                {
                    cachedUpdates.Add(new CoalesceEntry()
                    {
                        BlobData    = Optional.None(),
                        CoalesceKey = oldUpdate.CoalesceKey
                    });
                }
                return(cachedUpdates);
            })
                                  .SelectMany(t => t);

            var reify = bytecode.WithLatestFromBuffered(assets, (bc, ass) =>
            {
                var waitForDependencies = Task.WaitAll(new []
                {
                    bc.Dependencies.Select(d => cache.HasEntry(d.ToString()))
                    .ToObservableEnumerable()
                    .FirstAsync()
                    .ToTask(),
                    ass.Select(d => cache.HasEntry(d.ToString()))
                    .ToObservableEnumerable()
                    .FirstAsync()
                    .ToTask()
                }, TimeSpan.FromSeconds(60));

                if (waitForDependencies == false)
                {
                    throw new TimeoutException("Failed to load all assets dependencies.");
                }

                try
                {
                    return(new BytecodeGenerated(
                               new ProjectBytecode(
                                   reify: new Lambda(
                                       Signature.Action(Variable.This),
                                       Enumerable.Empty <BindVariable>(),
                                       new[]
                    {
                        ExpressionConverter.BytecodeFromSimpleLambda(() => ObjectTagRegistry.Clear()),

                        new CallLambda(bc.Reify, new ReadVariable(Variable.This)),
                    }),
                                   metadata: bc.Metadata,
                                   dependencies: bc.Dependencies))
                           .ToCoalesceEntry(BytecodeGenerated.MessageType));
                }
                catch (Exception)
                {
                    return(new BytecodeUpdated(
                               new Lambda(
                                   Signature.Action(),
                                   Enumerable.Empty <BindVariable>(),
                                   Enumerable.Empty <Statement>()))
                           .ToCoalesceEntry("invalid-byte-code"));
                }
            })
                        .CatchAndRetry(TimeSpan.FromSeconds(15),
                                       e =>
            {
                _logMessages.OnNext("Failed to refresh because: " + e.Message);
            });

            return(Observable.Merge(clearOldUpdates, reify, bytecodeUpdates));
        }
コード例 #2
0
ファイル: ProjectPreview.cs プロジェクト: yongaru/fuse-studio
        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);
        }