예제 #1
0
        public async Task <ExecutionOutputResult> ExecuteAsync(
            string sessionId,
            byte[] assemblyBytes,
            byte[] outputBufferBytes,
            bool includePerformance,
            CancellationToken cancellationToken
            )
        {
            // Note that _containers are never accessed through multiple threads for the same session id,
            // so atomicity is not required within same session id
            using var allocationCancellation = CancellationFactory.ContainerAllocation(cancellationToken);
            if (_containerPool.GetSessionContainer(sessionId) is not {
            } container)
            {
                if (_crashSuspensionManager.GetSuspension(sessionId, outputBufferBytes) is {} suspension)
                {
                    return(suspension);
                }

                try {
                    container = await _containerPool.AllocateSessionContainerAsync(sessionId, _cleanupWorker.QueueForCleanup, allocationCancellation.Token);
                }
                catch (OperationCanceledException ex) {
                    throw new ContainerAllocationException("Failed to allocate container within 5 seconds.", _containerPool.LastContainerPreallocationException ?? ex);
                }

                await _dockerClient.Containers.RenameContainerAsync(container.ContainerId, new ContainerRenameParameters {
                    NewName = _containerNameFormat.GenerateSessionContainerName(sessionId)
                }, cancellationToken);
            }

            var result = await _executionProcessor.ExecuteInContainerAsync(
                container,
                assemblyBytes,
                outputBufferBytes,
                includePerformance,
                cancellationToken
                );

            if (!result.IsOutputReadSuccess)
            {
                var containerCrashed = false;
                try {
                    var response = await _dockerClient.Containers.InspectContainerAsync(container.ContainerId, cancellationToken);

                    containerCrashed = !response.State.Running;
                }
                catch (DockerContainerNotFoundException) {
                    containerCrashed = true;
                }
                if (containerCrashed)
                {
                    _containerPool.RemoveSessionContainer(sessionId);
                }

                return(_crashSuspensionManager.SetSuspension(sessionId, result));
            }
            return(result);
        }
예제 #2
0
        public async Task <ExecutionOutputResult> ExecuteInContainerAsync(
            ActiveContainer container,
            byte[] assemblyBytes,
            byte[] outputBufferBytes,
            bool includePerformance,
            CancellationToken cancellationToken
            )
        {
            var outputStartMarker = Guid.NewGuid();
            var outputEndMarker   = Guid.NewGuid();
            await _stdinWriter.WriteCommandAsync(container.Stream, new ExecuteCommand(
                                                     assemblyBytes,
                                                     outputStartMarker,
                                                     outputEndMarker,
                                                     includePerformance
                                                     ), cancellationToken);

            const int OutputMarkerLength = 36; // length of guid

            byte[]? outputStartMarkerBytes = null;
            byte[]? outputEndMarkerBytes   = null;
            try {
                outputStartMarkerBytes = ArrayPool <byte> .Shared.Rent(OutputMarkerLength);

                outputEndMarkerBytes = ArrayPool <byte> .Shared.Rent(OutputMarkerLength);

                Utf8Formatter.TryFormat(outputStartMarker, outputStartMarkerBytes, out _);
                Utf8Formatter.TryFormat(outputEndMarker, outputEndMarkerBytes, out _);

                using var executionCancellation = CancellationFactory.ContainerExecution(cancellationToken);
                return(await _stdoutReader.ReadOutputAsync(
                           container.Stream,
                           outputBufferBytes,
                           outputStartMarkerBytes.AsMemory(0, OutputMarkerLength),
                           outputEndMarkerBytes.AsMemory(0, OutputMarkerLength),
                           executionCancellation.Token
                           ));
            }
            finally {
                if (outputStartMarkerBytes != null)
                {
                    ArrayPool <byte> .Shared.Return(outputStartMarkerBytes);
                }
                if (outputEndMarkerBytes != null)
                {
                    ArrayPool <byte> .Shared.Return(outputEndMarkerBytes);
                }
            }
        }