Example #1
0
        private async Task StartAsync()
        {
            base.Start();
            var eventService = services.GetRequiredService <IEventService>();

            eventService.Events <WorkspaceReadyEvent, IWorkspace>().On += (workspace) =>
            {
                logger?.LogInformation(
                    "Workspace ready {Time} after startup.",
                    DateTime.UtcNow - System.Diagnostics.Process.GetCurrentProcess().StartTime.ToUniversalTime()
                    );
            };

            // Before anything else, make sure to start the right background
            // thread on the Q# compilation loader to initialize serializers
            // and deserializers. Since that runs in the background, starting
            // the engine should not be blocked, and other services can
            // continue to initialize while the Q# compilation loader works.
            //
            // For more details, see:
            //     https://github.com/microsoft/qsharp-compiler/pull/727
            //     https://github.com/microsoft/qsharp-compiler/pull/810
            logger.LogDebug("Loading serialization and deserialziation protocols.");
            Protocols.Initialize();

            logger.LogDebug("Getting services required to start IQ# engine.");
            var serviceTasks = new
            {
                Snippets        = services.GetRequiredServiceInBackground <ISnippets>(logger),
                SymbolsResolver = services.GetRequiredServiceInBackground <ISymbolResolver>(logger),
                MagicResolver   = services.GetRequiredServiceInBackground <IMagicSymbolResolver>(logger),
                Workspace       = services.GetRequiredServiceInBackground <IWorkspace>(logger),
                References      = services.GetRequiredServiceInBackground <IReferences>(logger)
            };

            this.Snippets        = await serviceTasks.Snippets;
            this.SymbolsResolver = await serviceTasks.SymbolsResolver;
            this.MagicResolver   = await serviceTasks.MagicResolver;
            this.Workspace       = await serviceTasks.Workspace;
            var references = await serviceTasks.References;

            logger.LogDebug("Registering IQ# display and JSON encoders.");
            RegisterDisplayEncoder(new IQSharpSymbolToHtmlResultEncoder());
            RegisterDisplayEncoder(new IQSharpSymbolToTextResultEncoder());
            RegisterDisplayEncoder(new TaskStatusToTextEncoder());
            RegisterDisplayEncoder(new StateVectorToHtmlResultEncoder(configurationSource));
            RegisterDisplayEncoder(new StateVectorToTextResultEncoder(configurationSource));
            RegisterDisplayEncoder(new DataTableToHtmlEncoder());
            RegisterDisplayEncoder(new DataTableToTextEncoder());
            RegisterDisplayEncoder(new DisplayableExceptionToHtmlEncoder());
            RegisterDisplayEncoder(new DisplayableExceptionToTextEncoder());
            RegisterDisplayEncoder(new DisplayableHtmlElementEncoder());

            // For back-compat with older versions of qsharp.py <= 0.17.2105.144881
            // that expected the application/json MIME type for the JSON data.
            var userAgentVersion = metadataController.GetUserAgentVersion();

            logger.LogInformation($"userAgentVersion: {userAgentVersion}");
            var jsonMimeType = metadataController?.UserAgent?.StartsWith("qsharp.py") == true
                ? userAgentVersion != null && userAgentVersion > new Version(0, 17, 2105, 144881)
                    ? "application/x-qsharp-data"
                    : "application/json"
                : "application/x-qsharp-data";

            // Register JSON encoders, and make sure that Newtonsoft.Json
            // doesn't throw exceptions on reference loops.
            JsonConvert.DefaultSettings = () => new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            };
            RegisterJsonEncoder(jsonMimeType,
                                JsonConverters.AllConverters
                                .Concat(AzureClient.JsonConverters.AllConverters)
                                .ToArray());

            logger.LogDebug("Registering IQ# symbol resolvers.");
            RegisterSymbolResolver(this.SymbolsResolver);
            RegisterSymbolResolver(this.MagicResolver);

            logger.LogDebug("Loading known assemblies and registering package loading.");
            RegisterPackageLoadedEvent(services, logger, references);

            // Handle new shell messages.
            ShellRouter.RegisterHandlers <IQSharpEngine>();

            // Report performance after completing startup.
            performanceMonitor.Report();
            logger.LogInformation(
                "IQ# engine started successfully as process {Process}.",
                Process.GetCurrentProcess().Id
                );

            eventService?.TriggerServiceInitialized <IExecutionEngine>(this);

            var initializedSuccessfully = initializedSource.TrySetResult(true);

            #if DEBUG
            Debug.Assert(initializedSuccessfully, "Was unable to complete initialization task.");
            #endif
        }