Пример #1
0
        public async void BubblesCancellation()
        {
            try
            {
                //Arrange
                Setup();
                var bingTask = new TaskInstance()
                {
                    Enabled = true,
                    Name    = "Bing",
                    Version = "0.1.2",
                    Id      = Guid.NewGuid()
                };
                var pingTask = new TaskInstance()
                {
                    Enabled = true,
                    Name    = "Ping",
                    Version = "0.1.1",
                    Id      = Guid.NewGuid()
                };

                var bingVersion = new TaskVersion(bingTask.Version);
                var pingVersion = new TaskVersion(pingTask.Version);

                _jobServer
                .Setup(x => x.GetTaskContentZipAsync(It.IsAny <Guid>(), It.IsAny <TaskVersion>(), _ec.Object.CancellationToken))
                .Returns((Guid taskId, TaskVersion taskVersion, CancellationToken token) =>
                {
                    _ecTokenSource.Cancel();
                    return(Task.FromResult <Stream>(GetZipStream()));
                });

                var tasks = new List <TaskInstance>(new TaskInstance[] { bingTask, pingTask });

                //Act
                //should initiate a download with a mocked IJobServer, which sets a cancellation token and
                //download task is expected to be in cancelled state
                Task   downloadTask = _taskManager.DownloadAsync(_ec.Object, tasks);
                Task[] taskToWait   = { downloadTask, Task.Delay(2000) };
                //wait for the task to be cancelled to exit
                await Task.WhenAny(taskToWait);

                //Assert
                //verify task completed in less than 2sec and it is in cancelled state
                Assert.True(downloadTask.IsCompleted, $"{nameof(_taskManager.DownloadAsync)} timed out.");
                Assert.True(!downloadTask.IsFaulted, downloadTask.Exception?.ToString());
                Assert.True(downloadTask.IsCanceled);
                //check if the task.json was not downloaded for ping and bing tasks
                Assert.Equal(
                    0,
                    Directory.GetFiles(IOUtil.GetTasksPath(_hc), "*", SearchOption.AllDirectories).Length);
                //assert download was invoked only once, because the first task cancelled the second task download
                _jobServer
                .Verify(x => x.GetTaskContentZipAsync(It.IsAny <Guid>(), It.IsAny <TaskVersion>(), _ec.Object.CancellationToken), Times.Once());
            }
            finally
            {
                Teardown();
            }
        }
Пример #2
0
 public int TaskSetVersion(TaskVersion model)
 {
     using (RLib.DB.DbConn dbconn = Pub.GetConn())
     {
         var task = taskdal.GetDetail(dbconn, model.TaskId);
         if (task == null)
         {
             throw new MException("没有任务!");
         }
         dbconn.BeginTransaction();
         try
         {
             model.TaskId = task.TaskId;
             var versions = taskdal.AddVersion(dbconn, new Model.TaskVersion()
             {
                 CreateTime = DateTime.Now,
                 FilePath   = model.FilePath ?? "",
                 FileSize   = model.FileSize,
                 Remark     = model.Remark ?? "",
                 TaskId     = model.TaskId,
                 VersionId  = 0,
                 VersionNO  = DateTime.Now.ToString("yyyyMMddHHmmssfff" + "-" + model.TaskId),
                 Vstate     = 0
             });
             taskdal.SetVersion(dbconn, task.TaskId, versions.VersionId);
             dbconn.Commit();
             return(model.TaskId);
         }
         catch (Exception ex)
         {
             dbconn.Rollback();
             throw;
         }
     }
 }
        public async void RetryStreamException()
        {
            try
            {
                // Arrange.
                using (var tokenSource = new CancellationTokenSource())
                    using (var _hc = Setup(tokenSource))
                    {
                        var pingTask = new Pipelines.TaskStep()
                        {
                            Enabled   = true,
                            Reference = new Pipelines.TaskStepDefinitionReference()
                            {
                                Name    = "Ping",
                                Version = "0.1.1",
                                Id      = Guid.NewGuid()
                            }
                        };

                        var       pingVersion       = new TaskVersion(pingTask.Reference.Version);
                        Exception expectedException = new System.Net.Http.HttpRequestException("simulated network error");
                        _taskServer
                        .Setup(x => x.GetTaskContentZipAsync(It.IsAny <Guid>(), It.IsAny <TaskVersion>(), It.IsAny <CancellationToken>()))
                        .Returns((Guid taskId, TaskVersion taskVersion, CancellationToken token) =>
                        {
                            return(Task.FromResult <Stream>(new ExceptionStream()));
                        });

                        var tasks = new List <Pipelines.TaskStep>(new Pipelines.TaskStep[] { pingTask });

                        //Act
                        Exception actualException = null;
                        try
                        {
                            await _taskManager.DownloadAsync(_ec.Object, tasks);
                        }
                        catch (Exception ex)
                        {
                            actualException = ex;
                        }

                        //Assert
                        //verify task completed in less than 2sec and it is in failed state state
                        Assert.Equal("NotImplementedException", actualException.GetType().Name);

                        //assert download was invoked 3 times, because we retry on task download
                        _taskServer
                        .Verify(x => x.GetTaskContentZipAsync(It.IsAny <Guid>(), It.IsAny <TaskVersion>(), It.IsAny <CancellationToken>()), Times.Exactly(3));

                        //see if the task.json was not downloaded
                        Assert.Equal(
                            0,
                            Directory.GetFiles(_hc.GetDirectory(WellKnownDirectory.Tasks), "*", SearchOption.AllDirectories).Length);
                    }
            }
            finally
            {
                Teardown();
            }
        }
Пример #4
0
        public void GetTasks()
        {
            // Arrange.
            const string taskName = "task name";
            var          task     = new Task(taskName);

            var date        = new DateTime();
            var taskVersion = new TaskVersion(date);

            var versions = new SortedDictionary <DateTime, TaskVersion>();

            versions.Add(date, taskVersion);

            var taskVersions = new Dictionary <
                string, SortedDictionary <DateTime, TaskVersion>
                >();

            taskVersions.Add(taskName, versions);

            var store = MockRepository.GeneratePartialMock <MemoryTaskStore>();

            store.Expect(s => s.TaskVersions).Return(taskVersions);
            store.Expect(s => s.New(taskName, versions)).Return(task);

            // Act.
            var res = store.Tasks.ToList();

            // Assert.
            store.VerifyAllExpectations();
            Assert.AreEqual(1, res.Count());
            Assert.AreEqual(task, res.First());
        }
Пример #5
0
 /// <summary>
 /// 批量上传版本变指定为当前版本
 /// </summary>
 /// <param name="model"></param>
 /// <param name="tag"></param>
 public void BatchTaskVersion(TaskVersion model, int tag)
 {
     using (RLib.DB.DbConn dbconn = Pub.GetConn())
     {
         var tasks = taskdal.GetAllTask(dbconn, tag);
         if (tasks.Count == 0)
         {
             throw new MException("没有任务!");
         }
         dbconn.BeginTransaction();
         try
         {
             foreach (var a in tasks)
             {
                 model.TaskId = a.TaskId;
                 var versions = taskdal.AddVersion(dbconn, model);
                 taskdal.SetVersion(dbconn, a.TaskId, versions.VersionId);
             }
             dbconn.Commit();
         }
         catch (Exception ex)
         {
             dbconn.Rollback();
             throw;
         }
     }
 }
Пример #6
0
        public async void BubblesCancellation()
        {
            try
            {
                //Arrange
                Setup();
                var bingTask = new TaskInstance()
                {
                    Enabled = true,
                    Name = "Bing",
                    Version = "0.1.2",
                    Id = Guid.NewGuid()
                };
                var pingTask = new TaskInstance()
                {
                    Enabled = true,
                    Name = "Ping",
                    Version = "0.1.1",
                    Id = Guid.NewGuid()
                };

                var bingVersion = new TaskVersion(bingTask.Version);
                var pingVersion = new TaskVersion(pingTask.Version);

                _taskServer
                    .Setup(x => x.GetTaskContentZipAsync(It.IsAny<Guid>(), It.IsAny<TaskVersion>(), _ec.Object.CancellationToken))
                    .Returns((Guid taskId, TaskVersion taskVersion, CancellationToken token) =>
                    {
                        _ecTokenSource.Cancel();
                        return Task.FromResult<Stream>(GetZipStream());
                    });

                var tasks = new List<TaskInstance>(new TaskInstance[] { bingTask, pingTask });

                //Act
                //should initiate a download with a mocked IJobServer, which sets a cancellation token and
                //download task is expected to be in cancelled state
                Task downloadTask = _taskManager.DownloadAsync(_ec.Object, tasks);
                Task[] taskToWait = { downloadTask, Task.Delay(2000) };
                //wait for the task to be cancelled to exit
                await Task.WhenAny(taskToWait);

                //Assert
                //verify task completed in less than 2sec and it is in cancelled state
                Assert.True(downloadTask.IsCompleted, $"{nameof(_taskManager.DownloadAsync)} timed out.");
                Assert.True(!downloadTask.IsFaulted, downloadTask.Exception?.ToString());
                Assert.True(downloadTask.IsCanceled);
                //check if the task.json was not downloaded for ping and bing tasks
                Assert.Equal(
                    0,
                    Directory.GetFiles(IOUtil.GetTasksPath(_hc), "*", SearchOption.AllDirectories).Length);
                //assert download was invoked only once, because the first task cancelled the second task download
                _taskServer
                    .Verify(x => x.GetTaskContentZipAsync(It.IsAny<Guid>(), It.IsAny<TaskVersion>(), _ec.Object.CancellationToken), Times.Once());
            }
            finally
            {
                Teardown();
            }
        }
Пример #7
0
        public void SaveNoTaskVersionException()
        {
            // Arrange.
            const string taskName = "name";
            TaskVersion  version  = null;
            var          store    = new MemoryTaskStore();

            // Act and assert.
            store.Save(taskName, version);
        }
Пример #8
0
        public void SaveEmptyTaskNameException()
        {
            // Arrange.
            const string taskName = " ";
            var          version  = new TaskVersion(new DateTime());
            var          store    = new MemoryTaskStore();

            // Act and assert.
            store.Save(taskName, version);
        }
Пример #9
0
        public void CtorSavesDateRef()
        {
            // Arrange.
            var date = new DateTime(2000, 1, 1);

            // Act.
            var version = new TaskVersion(date);

            // Assert.
            Assert.AreEqual(date, version.Date);
        }
Пример #10
0
 public TaskVersion AddTaskVersion(TaskVersion model)
 {
     if (model.TaskId <= 0)
     {
         throw new MException("任务ID不能为空!");
     }
     using (RLib.DB.DbConn dbconn = Pub.GetConn())
     {
         var versions = taskdal.AddVersion(dbconn, model);
         return(versions);
     }
 }
Пример #11
0
        public async void BubblesNetworkException()
        {
            try
            {
                // Arrange.
                Setup();
                var pingTask = new Pipelines.TaskStep()
                {
                    Enabled   = true,
                    Reference = new Pipelines.TaskStepDefinitionReference()
                    {
                        Name    = "Ping",
                        Version = "0.1.1",
                        Id      = Guid.NewGuid()
                    }
                };

                var       pingVersion       = new TaskVersion(pingTask.Reference.Version);
                Exception expectedException = new System.Net.Http.HttpRequestException("simulated network error");
                _taskServer
                .Setup(x => x.GetTaskContentZipAsync(It.IsAny <Guid>(), It.IsAny <TaskVersion>(), _ec.Object.CancellationToken))
                .Returns((Guid taskId, TaskVersion taskVersion, CancellationToken token) =>
                {
                    throw expectedException;
                });

                var tasks = new List <Pipelines.TaskStep>(new Pipelines.TaskStep[] { pingTask });

                //Act
                Exception actualException = null;
                try
                {
                    await _taskManager.DownloadAsync(_ec.Object, tasks);
                }
                catch (Exception ex)
                {
                    actualException = ex;
                }

                //Assert
                //verify task completed in less than 2sec and it is in failed state state
                Assert.Equal(expectedException, actualException);
                //see if the task.json was not downloaded
                Assert.Equal(
                    0,
                    Directory.GetFiles(_hc.GetDirectory(WellKnownDirectory.Tasks), "*", SearchOption.AllDirectories).Length);
            }
            finally
            {
                Teardown();
            }
        }
Пример #12
0
        public Task <Stream> GetTaskContentZipAsync(Guid taskId, TaskVersion taskVersion, CancellationToken token)
        {
            String taskZip = Path.Join(HostContext.GetDirectory(WellKnownDirectory.Externals), "Tasks", taskId.ToString() + ".zip");

            if (File.Exists(taskZip))
            {
                return(Task.FromResult <Stream>(new FileStream(taskZip, FileMode.Open, FileAccess.Read, FileShare.Read)));
            }
            else
            {
                throw new Exception("A step specified a task which does not exist in the L1 test framework. Any tasks used by L1 tests must be added manually.");
            }
        }
Пример #13
0
        public Task <Stream> GetTaskContentZipAsync(Guid taskId, TaskVersion taskVersion, CancellationToken token)
        {
            String baseDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            String taskZipsPath  = Path.Join(baseDirectory, "TaskZips");

            foreach (String zip in Directory.GetFiles(taskZipsPath))
            {
                String zipName = Path.GetFileNameWithoutExtension(zip);
                if (zipName.Equals(taskId.ToString()))
                {
                    return(Task.FromResult <Stream>(new FileStream(zip, FileMode.Open)));
                }
            }

            return(Task.FromResult <Stream>(null));
        }
Пример #14
0
        private Type GetTaskType(string name, string version)
        {
            var taskVersion = new TaskVersion(name, version);

            if (_typeMap.TryGetValue(taskVersion, out Type type))
            {
                return(type);
            }

            foreach (NamedTypeDescriptor <TDescribed> descriptor in _descriptors)
            {
                if (IsTaskMatch(name, version, descriptor))
                {
                    _typeMap.TryAdd(taskVersion, descriptor.Type);
                    return(descriptor.Type);
                }
            }

            return(null);
        }
Пример #15
0
        public void SaveCreatesTaskAndAppendsVersion()
        {
            // Arrange.
            const string name     = "task name";
            var          date     = new DateTime(2000, 1, 1);
            var          version  = new TaskVersion(date);
            var          task     = new Task(name);
            var          versions = new SortedDictionary <DateTime, TaskVersion>();
            var          store    = MockRepository.GeneratePartialMock <MemoryTaskStore>();

            store.Expect(s => s.GetVersions(name)).Return(versions);
            store.Expect(s => s.New(name, versions)).Return(task);

            // Act.
            var res = store.Save(name, version);

            // Assert.
            store.VerifyAllExpectations();
            Assert.AreEqual(task, res);
            Assert.AreEqual(1, versions.Count());
            Assert.AreEqual(version, versions[date]);
        }
Пример #16
0
        public void NewCreatesTaskWithSpecifiedName()
        {
            // Arrange.
            const string taskName = "task name";

            var date    = new DateTime();
            var version = new TaskVersion(date);

            var versions = new SortedDictionary <DateTime, TaskVersion>();

            versions.Add(date, version);

            var store = new MemoryTaskStore();

            // Act.
            var task = store.New(taskName, versions);

            // Assert.
            Assert.AreEqual(taskName, task.Name);
            Assert.AreEqual(1, task.Versions.Count());
            Assert.AreEqual(version, task.Versions.First());
        }
Пример #17
0
    private Task CreateTaskWithVersion(string text, string id, DateTime start, DateTime end, int complete)
    {
        Task task = new Task(text, id, start, end);

        task.Complete = complete;

        TaskVersion version1 = new TaskVersion();

        version1.Start    = start.AddDays(30);
        version1.End      = end.AddDays(31);
        version1.Complete = complete - 20;
        task.Versions.Add(version1);

        TaskVersion version2 = new TaskVersion();

        version2.Start    = start.AddDays(-1);
        version2.End      = end.AddDays(-1);
        version2.Complete = complete - 10;
        task.Versions.Add(version2);

        return(task);
    }
Пример #18
0
        public void CreateDelegates()
        {
            // Arrange.
            var          date           = new DateTime(2000, 1, 1);
            const string serializedTask = "serialized task";
            const string taskName       = "task name";
            var          parserResult   = new ParserResult {
                Name = taskName
            };
            var taskVersion = new TaskVersion(date);
            var task        = new Task(taskName);
            var parser      = MockRepository.GenerateStrictMock <ITaskParser>();
            var store       = MockRepository.GenerateStrictMock <ITaskStore>();

            var factory =
                MockRepository.GeneratePartialMock <TaskFactory>(parser, store);

            parser
            .Expect(p => p.Parse(serializedTask))
            .Return(parserResult);
            factory
            .Expect(f => f.New(date, parserResult))
            .Return(taskVersion);
            store
            .Expect(s => s.Save(taskName, taskVersion))
            .Return(task);

            // Act.
            var res = factory.Create(date, serializedTask);

            // Assert.
            parser.VerifyAllExpectations();
            factory.VerifyAllExpectations();
            store.VerifyAllExpectations();
            Assert.AreEqual(task, res);
        }
Пример #19
0
 //-----------------------------------------------------------------
 // Task Manager: Query and Download Task
 //-----------------------------------------------------------------
 public Task <Stream> GetTaskContentZipAsync(Guid taskId, TaskVersion taskVersion, CancellationToken token)
 {
     ArgUtil.Equal(RunMode.Normal, HostContext.RunMode, nameof(HostContext.RunMode));
     CheckConnection();
     return(_taskAgentClient.GetTaskContentZipAsync(taskId, taskVersion, cancellationToken: token));
 }
Пример #20
0
            public async Task EnsureCachedAsync(TaskDefinition task, CancellationToken token)
            {
                Trace.Entering();
                ArgUtil.NotNull(task, nameof(task));
                ArgUtil.NotNullOrEmpty(task.Version, nameof(task.Version));

                // first check to see if we already have the task
                string destDirectory = GetTaskDirectory(task);

                Trace.Info($"Ensuring task exists: ID '{task.Id}', version '{task.Version}', name '{task.Name}', directory '{destDirectory}'.");
                if (File.Exists(destDirectory + ".completed"))
                {
                    Trace.Info("Task already downloaded.");
                    return;
                }

                // Invalidate the local cache.
                _localTasks = null;

                // delete existing task folder.
                Trace.Verbose("Deleting task destination folder: {0}", destDirectory);
                IOUtil.DeleteDirectory(destDirectory, CancellationToken.None);

                // Inform the user that a download is taking place. The download could take a while if
                // the task zip is large. It would be nice to print the localized name, but it is not
                // available from the reference included in the job message.
                _term.WriteLine(StringUtil.Loc("DownloadingTask0", task.Name));
                string zipFile;
                var    version = new TaskVersion(task.Version);

                //download and extract task in a temp folder and rename it on success
                string tempDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Tasks), "_temp_" + Guid.NewGuid());

                try
                {
                    Directory.CreateDirectory(tempDirectory);
                    zipFile = Path.Combine(tempDirectory, string.Format("{0}.zip", Guid.NewGuid()));
                    //open zip stream in async mode
                    using (FileStream fs = new FileStream(zipFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
                    {
                        using (Stream result = await HttpClient.GetTaskContentZipAsync(task.Id, version, token))
                        {
                            //81920 is the default used by System.IO.Stream.CopyTo and is under the large object heap threshold (85k).
                            await result.CopyToAsync(fs, 81920, token);

                            await fs.FlushAsync(token);
                        }
                    }

                    Directory.CreateDirectory(destDirectory);
                    ZipFile.ExtractToDirectory(zipFile, destDirectory);

                    Trace.Verbose("Create watermark file indicate task download succeed.");
                    File.WriteAllText(destDirectory + ".completed", DateTime.UtcNow.ToString());

                    Trace.Info("Finished getting task.");
                }
                finally
                {
                    try
                    {
                        //if the temp folder wasn't moved -> wipe it
                        if (Directory.Exists(tempDirectory))
                        {
                            Trace.Verbose("Deleting task temp folder: {0}", tempDirectory);
                            IOUtil.DeleteDirectory(tempDirectory, CancellationToken.None); // Don't cancel this cleanup and should be pretty fast.
                        }
                    }
                    catch (Exception ex)
                    {
                        //it is not critical if we fail to delete the temp folder
                        Trace.Warning("Failed to delete temp folder '{0}'. Exception: {1}", tempDirectory, ex);
                        Trace.Warning(StringUtil.Loc("FailedDeletingTempDirectory0Message1", tempDirectory, ex.Message));
                    }
                }
            }
Пример #21
0
        //设置任务版本
        public ActionResult TaskSetVersion(TaskVersion model)
        {
            var model2 = manageApiBll.TaskSetVersion(model);

            return(ApiSuccess(model2));
        }
Пример #22
0
        private async Task DownloadAsync(IExecutionContext executionContext, Pipelines.TaskStepDefinitionReference task)
        {
            Trace.Entering();
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            ArgUtil.NotNull(task, nameof(task));
            ArgUtil.NotNullOrEmpty(task.Version, nameof(task.Version));
            var taskServer = HostContext.GetService <ITaskServer>();

            // first check to see if we already have the task
            string destDirectory = GetDirectory(task);

            Trace.Info($"Ensuring task exists: ID '{task.Id}', version '{task.Version}', name '{task.Name}', directory '{destDirectory}'.");

            var           configurationStore = HostContext.GetService <IConfigurationStore>();
            AgentSettings settings           = configurationStore.GetSettings();
            Boolean       signingEnabled     = !String.IsNullOrEmpty(settings.Fingerprint);

            if (File.Exists(destDirectory + ".completed") && !signingEnabled)
            {
                executionContext.Debug($"Task '{task.Name}' already downloaded at '{destDirectory}'.");
                return;
            }

            String taskZipPath = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.TaskZips), $"{task.Name}_{task.Id}_{task.Version}.zip");

            if (signingEnabled && File.Exists(taskZipPath))
            {
                executionContext.Debug($"Task '{task.Name}' already downloaded at '{taskZipPath}'.");

                // We need to extract the zip now because the task.json metadata for the task is used in JobExtension.InitializeJob.
                // This is fine because we overwrite the contents at task run time.
                if (!File.Exists(destDirectory + ".completed"))
                {
                    // The zip exists but it hasn't been extracted yet.
                    IOUtil.DeleteDirectory(destDirectory, executionContext.CancellationToken);
                    ExtractZip(taskZipPath, destDirectory);
                }

                return;
            }

            // delete existing task folder.
            Trace.Verbose("Deleting task destination folder: {0}", destDirectory);
            IOUtil.DeleteDirectory(destDirectory, CancellationToken.None);

            // Inform the user that a download is taking place. The download could take a while if
            // the task zip is large. It would be nice to print the localized name, but it is not
            // available from the reference included in the job message.
            executionContext.Output(StringUtil.Loc("DownloadingTask0", task.Name, task.Version));
            string zipFile = string.Empty;
            var    version = new TaskVersion(task.Version);

            //download and extract task in a temp folder and rename it on success
            string tempDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Tasks), "_temp_" + Guid.NewGuid());

            try
            {
                Directory.CreateDirectory(tempDirectory);
                int retryCount = 0;

                // Allow up to 20 * 60s for any task to be downloaded from service.
                // Base on Kusto, the longest we have on the service today is over 850 seconds.
                // Timeout limit can be overwrite by environment variable
                if (!int.TryParse(Environment.GetEnvironmentVariable("VSTS_TASK_DOWNLOAD_TIMEOUT") ?? string.Empty, out int timeoutSeconds))
                {
                    timeoutSeconds = 20 * 60;
                }

                while (retryCount < 3)
                {
                    using (var taskDownloadTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSeconds)))
                        using (var taskDownloadCancellation = CancellationTokenSource.CreateLinkedTokenSource(taskDownloadTimeout.Token, executionContext.CancellationToken))
                        {
                            try
                            {
                                zipFile = Path.Combine(tempDirectory, string.Format("{0}.zip", Guid.NewGuid()));

                                //open zip stream in async mode
                                using (FileStream fs = new FileStream(zipFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: _defaultFileStreamBufferSize, useAsync: true))
                                    using (Stream result = await taskServer.GetTaskContentZipAsync(task.Id, version, taskDownloadCancellation.Token))
                                    {
                                        await result.CopyToAsync(fs, _defaultCopyBufferSize, taskDownloadCancellation.Token);

                                        await fs.FlushAsync(taskDownloadCancellation.Token);

                                        // download succeed, break out the retry loop.
                                        break;
                                    }
                            }
                            catch (OperationCanceledException) when(executionContext.CancellationToken.IsCancellationRequested)
                            {
                                Trace.Info($"Task download has been cancelled.");
                                throw;
                            }
                            catch (Exception ex) when(retryCount < 2)
                            {
                                retryCount++;
                                Trace.Error($"Fail to download task '{task.Id} ({task.Name}/{task.Version})' -- Attempt: {retryCount}");
                                Trace.Error(ex);
                                if (taskDownloadTimeout.Token.IsCancellationRequested)
                                {
                                    // task download didn't finish within timeout
                                    executionContext.Warning(StringUtil.Loc("TaskDownloadTimeout", task.Name, timeoutSeconds));
                                }
                                else
                                {
                                    executionContext.Warning(StringUtil.Loc("TaskDownloadFailed", task.Name, ex.Message));
                                    if (ex.InnerException != null)
                                    {
                                        executionContext.Warning("Inner Exception: {ex.InnerException.Message}");
                                    }
                                }
                            }
                        }

                    if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("VSTS_TASK_DOWNLOAD_NO_BACKOFF")))
                    {
                        var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30));
                        executionContext.Warning($"Back off {backOff.TotalSeconds} seconds before retry.");
                        await Task.Delay(backOff);
                    }
                }

                if (signingEnabled)
                {
                    Directory.CreateDirectory(HostContext.GetDirectory(WellKnownDirectory.TaskZips));

                    // Copy downloaded zip to the cache on disk for future extraction.
                    executionContext.Debug($"Copying from {zipFile} to {taskZipPath}");
                    File.Copy(zipFile, taskZipPath);
                }

                // We need to extract the zip regardless of whether or not signing is enabled because the task.json metadata for the task is used in JobExtension.InitializeJob.
                // This is fine because we overwrite the contents at task run time.
                Directory.CreateDirectory(destDirectory);
                ExtractZip(zipFile, destDirectory);

                executionContext.Debug($"Task '{task.Name}' has been downloaded into '{(signingEnabled ? taskZipPath : destDirectory)}'.");
                Trace.Info("Finished getting task.");
            }
            finally
            {
                try
                {
                    //if the temp folder wasn't moved -> wipe it
                    if (Directory.Exists(tempDirectory))
                    {
                        Trace.Verbose("Deleting task temp folder: {0}", tempDirectory);
                        IOUtil.DeleteDirectory(tempDirectory, CancellationToken.None); // Don't cancel this cleanup and should be pretty fast.
                    }
                }
                catch (Exception ex)
                {
                    //it is not critical if we fail to delete the temp folder
                    Trace.Warning("Failed to delete temp folder '{0}'. Exception: {1}", tempDirectory, ex);
                    executionContext.Warning(StringUtil.Loc("FailedDeletingTempDirectory0Message1", tempDirectory, ex.Message));
                }
            }
        }
Пример #23
0
 //-----------------------------------------------------------------
 // Task Manager: Query and Download Task
 //-----------------------------------------------------------------
 public Task<Stream> GetTaskContentZipAsync(Guid taskId, TaskVersion taskVersion, CancellationToken token)
 {
     CheckConnection();
     return _taskAgentClient.GetTaskContentZipAsync(taskId, taskVersion, null, token);
 }
Пример #24
0
 //-----------------------------------------------------------------
 // Task Manager: Query and Download Task
 //-----------------------------------------------------------------
 public Task <Stream> GetTaskContentZipAsync(Guid taskId, TaskVersion taskVersion, CancellationToken token)
 {
     CheckConnection();
     return(_taskAgentClient.GetTaskContentZipAsync(taskId, taskVersion, null, token));
 }
        public async void BubblesCancellation()
        {
            try
            {
                //Arrange
                using (var tokenSource = new CancellationTokenSource())
                    using (var _hc = Setup(tokenSource))
                    {
                        var bingTask = new Pipelines.TaskStep()
                        {
                            Enabled   = true,
                            Reference = new Pipelines.TaskStepDefinitionReference()
                            {
                                Name    = "Bing",
                                Version = "0.1.2",
                                Id      = Guid.NewGuid()
                            }
                        };
                        var pingTask = new Pipelines.TaskStep()
                        {
                            Enabled   = true,
                            Reference = new Pipelines.TaskStepDefinitionReference()
                            {
                                Name    = "Ping",
                                Version = "0.1.1",
                                Id      = Guid.NewGuid()
                            }
                        };

                        var bingVersion = new TaskVersion(bingTask.Reference.Version);
                        var pingVersion = new TaskVersion(pingTask.Reference.Version);

                        _taskServer
                        .Setup(x => x.GetTaskContentZipAsync(It.IsAny <Guid>(), It.IsAny <TaskVersion>(), It.IsAny <CancellationToken>()))
                        .Returns((Guid taskId, TaskVersion taskVersion, CancellationToken token) =>
                        {
                            tokenSource.Cancel();
                            tokenSource.Token.ThrowIfCancellationRequested();
                            return(null);
                        });

                        var tasks = new List <Pipelines.TaskStep>(new Pipelines.TaskStep[] { bingTask, pingTask });

                        //Act
                        //should initiate a download with a mocked IJobServer, which sets a cancellation token and
                        //download task is expected to be in cancelled state
                        Task   downloadTask = _taskManager.DownloadAsync(_ec.Object, tasks);
                        Task[] taskToWait   = { downloadTask, Task.Delay(2000) };
                        //wait for the task to be cancelled to exit
                        await Task.WhenAny(taskToWait);

                        //Assert
                        //verify task completed in less than 2sec and it is in cancelled state
                        Assert.True(downloadTask.IsCompleted, $"{nameof(_taskManager.DownloadAsync)} timed out.");
                        Assert.True(!downloadTask.IsFaulted, downloadTask.Exception?.ToString());
                        Assert.True(downloadTask.IsCanceled);
                        //check if the task.json was not downloaded for ping and bing tasks
                        Assert.Equal(
                            0,
                            Directory.GetFiles(_hc.GetDirectory(WellKnownDirectory.Tasks), "*", SearchOption.AllDirectories).Length);
                        //assert download was invoked only once, because the first task cancelled the second task download
                        _taskServer
                        .Verify(x => x.GetTaskContentZipAsync(It.IsAny <Guid>(), It.IsAny <TaskVersion>(), It.IsAny <CancellationToken>()), Times.Once());
                    }
            }
            finally
            {
                Teardown();
            }
        }
Пример #26
0
        public async void BubblesNetworkException()
        {
            try
            {
                // Arrange.
                Setup();
                var pingTask = new TaskInstance()
                {
                    Enabled = true,
                    Name = "Ping",
                    Version = "0.1.1",
                    Id = Guid.NewGuid()
                };

                var pingVersion = new TaskVersion(pingTask.Version);
                Exception expectedException = new System.Net.Http.HttpRequestException("simulated network error");
                _taskServer
                    .Setup(x => x.GetTaskContentZipAsync(It.IsAny<Guid>(), It.IsAny<TaskVersion>(), _ec.Object.CancellationToken))
                    .Returns((Guid taskId, TaskVersion taskVersion, CancellationToken token) =>
                    {
                        throw expectedException;
                    });

                var tasks = new List<TaskInstance>(new TaskInstance[] { pingTask });

                //Act
                Exception actualException = null;
                try
                {
                    await _taskManager.DownloadAsync(_ec.Object, tasks);
                }
                catch (Exception ex)
                {
                    actualException = ex;
                }

                //Assert
                //verify task completed in less than 2sec and it is in failed state state
                Assert.Equal(expectedException, actualException);
                //see if the task.json was not downloaded
                Assert.Equal(
                    0,
                    Directory.GetFiles(IOUtil.GetTasksPath(_hc), "*", SearchOption.AllDirectories).Length);
            }
            finally
            {
                Teardown();
            }
        }
Пример #27
0
        //-----------------------------------------------------------------
        // Task Manager: Query and Download Task
        //-----------------------------------------------------------------

        public Task <TaskDefinition> GetTaskDefinitionAsync(Guid taskId, TaskVersion taskVersion, CancellationToken token)
        {
            return(_taskAgentClient.GetTaskDefinitionAsync(taskId, taskVersion, null, null, null, token));
        }
Пример #28
0
        private async Task DownloadAsync(IExecutionContext executionContext, TaskReference task)
        {
            Trace.Entering();
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            ArgUtil.NotNull(task, nameof(task));
            ArgUtil.NotNullOrEmpty(task.Version, nameof(task.Version));
            var jobServer = HostContext.GetService <IJobServer>();

            // first check to see if we already have the task
            string destDirectory = GetDirectory(task);

            Trace.Info($"Ensuring task exists: ID '{task.Id}', version '{task.Version}', name '{task.Name}', directory '{destDirectory}'.");
            if (Directory.Exists(destDirectory))
            {
                Trace.Info("Task already downloaded.");
                return;
            }

            Trace.Info("Getting task.");
            string zipFile;
            var    version = new TaskVersion(task.Version);

            //download and extract task in a temp folder and rename it on success
            string tempDirectory = Path.Combine(IOUtil.GetTasksPath(HostContext), "_temp_" + Guid.NewGuid());

            try
            {
                Directory.CreateDirectory(tempDirectory);
                zipFile = Path.Combine(tempDirectory, string.Format("{0}.zip", Guid.NewGuid()));
                //open zip stream in async mode
                using (FileStream fs = new FileStream(zipFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
                {
                    using (Stream result = await jobServer.GetTaskContentZipAsync(task.Id, version, executionContext.CancellationToken))
                    {
                        //81920 is the default used by System.IO.Stream.CopyTo and is under the large object heap threshold (85k).
                        await result.CopyToAsync(fs, 81920, executionContext.CancellationToken);

                        await fs.FlushAsync(executionContext.CancellationToken);
                    }
                }

                ZipFile.ExtractToDirectory(zipFile, tempDirectory);
                File.Delete(zipFile);
                Directory.CreateDirectory(Path.GetDirectoryName(destDirectory));
                Directory.Move(tempDirectory, destDirectory);
                Trace.Info("Finished getting task.");
            }
            finally
            {
                try
                {
                    //if the temp folder wasn't moved -> wipe it
                    if (Directory.Exists(tempDirectory))
                    {
                        Trace.Verbose("Deleting task temp folder: {0}", tempDirectory);
                        IOUtil.DeleteDirectory(tempDirectory, CancellationToken.None); // Don't cancel this cleanup and should be pretty fast.
                    }
                }
                catch (Exception ex)
                {
                    //it is not critical if we fail to delete the temp folder
                    Trace.Warning("Failed to delete temp folder '{0}'. Exception: {1}", tempDirectory, ex);
                    executionContext.Warning(StringUtil.Loc("FailedDeletingTempDirectory0Message1", tempDirectory, ex.Message));
                }
            }
        }
Пример #29
0
        private async Task DownloadAsync(IExecutionContext executionContext, TaskReference task)
        {
            Trace.Entering();
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            ArgUtil.NotNull(task, nameof(task));
            ArgUtil.NotNullOrEmpty(task.Version, nameof(task.Version));
            var taskServer = HostContext.GetService<ITaskServer>();

            // first check to see if we already have the task
            string destDirectory = GetDirectory(task);
            Trace.Info($"Ensuring task exists: ID '{task.Id}', version '{task.Version}', name '{task.Name}', directory '{destDirectory}'.");
            if (Directory.Exists(destDirectory))
            {
                Trace.Info("Task already downloaded.");
                return;
            }

            Trace.Info("Getting task.");
            string zipFile;
            var version = new TaskVersion(task.Version);

            //download and extract task in a temp folder and rename it on success
            string tempDirectory = Path.Combine(IOUtil.GetTasksPath(HostContext), "_temp_" + Guid.NewGuid());
            try
            {
                Directory.CreateDirectory(tempDirectory);
                zipFile = Path.Combine(tempDirectory, string.Format("{0}.zip", Guid.NewGuid()));
                //open zip stream in async mode
                using (FileStream fs = new FileStream(zipFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
                {
                    using (Stream result = await taskServer.GetTaskContentZipAsync(task.Id, version, executionContext.CancellationToken))
                    {
                        //81920 is the default used by System.IO.Stream.CopyTo and is under the large object heap threshold (85k). 
                        await result.CopyToAsync(fs, 81920, executionContext.CancellationToken);
                        await fs.FlushAsync(executionContext.CancellationToken);
                    }
                }

                ZipFile.ExtractToDirectory(zipFile, tempDirectory);
                File.Delete(zipFile);
                Directory.CreateDirectory(Path.GetDirectoryName(destDirectory));
                Directory.Move(tempDirectory, destDirectory);
                Trace.Info("Finished getting task.");
            }
            finally
            {
                try
                {
                    //if the temp folder wasn't moved -> wipe it
                    if (Directory.Exists(tempDirectory))
                    {
                        Trace.Verbose("Deleting task temp folder: {0}", tempDirectory);
                        IOUtil.DeleteDirectory(tempDirectory, CancellationToken.None); // Don't cancel this cleanup and should be pretty fast.
                    }
                }
                catch (Exception ex)
                {
                    //it is not critical if we fail to delete the temp folder
                    Trace.Warning("Failed to delete temp folder '{0}'. Exception: {1}", tempDirectory, ex);
                    executionContext.Warning(StringUtil.Loc("FailedDeletingTempDirectory0Message1", tempDirectory, ex.Message));
                }
            }
        }