public async Task <IActionResult> Add(ArticleView result) { //if (await _articleService.CheckIfSlugExist(result.Slug)) //{ // ModelState.AddModelError("", "Artykuł z tym linkiem już istnieje!"); //} //if (!ModelState.IsValid) //{ // ViewBag.Categories = await _categoryService.GetAll(); // ViewBag.Tags = await _tagService.GetAll(); // return View(result); //} var user = await _userManager.GetUserAsync(User); var articleModel = ArticleHelpers.ConvertToModel(result, user, "https://theraphosidae.pl"); var article = await _articleService.Create(articleModel); if (article == false) { return(RedirectToAction("Index", "Dashboard")); } var photo = await _cloudinaryService.AddFile(result.FeaturedImg, articleModel); //await _taxonomyService.SaveCategories(await _categoryService.GetCategoriesByName(result.Categories), articleModel); //await _taxonomyService.SaveTags(await _tagService.GetCategoriesByNames(result.Tags), articleModel); return(RedirectToAction("List")); }
public async Task <IActionResult> Edit(ArticleView result) { var article = await _articleService.Get(result.Id); // sprawdzamy dopiero jeżeli tytuł się if (result.Slug != article.Slug) { // sprawdzic czy sam sobą nie jest czasem if (await _articleService.CheckIfSlugExist(result.Slug)) { ModelState.AddModelError("", "Wpis o podanym linku istnieje"); } } if (!ModelState.IsValid) { // 1. Pobieranie listy tagów oraz kategorii ViewBag.Categories = await _categoryService.GetAll(); ViewBag.Tags = await _tagService.GetAll(); return(View(result)); } // 2. Poprawnie zwalidowane post zapisuję do bazy danych // a. Jeżeli nastąpiła zamiana zdjęcia do zapisujemy if (result.IsPhotoEdited) { // Usuwanie starego zdjęcia tylko pod warunkiem jeżeli istnieje if (article.Image != null) { // usuwanie starego zdjęcia _cloudService.DeleteFile(article.Image.Id); } // Jeżeli zostało wgrane nowe zdjęcie to je zapisz i przypisz if (result.FeaturedImg != null) { var medium = await _cloudService.AddFile(result.FeaturedImg); article.Image = medium; } } // b. Aktualizacja wpisu var seoSettings = await _seoService.GetSeoSettings(); await _articleService.Update(ArticleHelpers.MergeViewWithModel(article, result, seoSettings.MainUrl)); // c. Aktualizacja taxonomies await _taxonomyService.Delete(result.Id); await _taxonomyService.SaveCategories(await _categoryService.GetCategoriesByNames(result.Categories), article); await _taxonomyService.SaveTags(await _tagService.GetCategoriesByNames(result.Tags), article); return(RedirectToAction("List")); }
public async Task <IActionResult> Details(int Id) { var articleModel = await _articleService.Get(Id); await _articleService.IncrementArticleViews(Id); ViewData["Comment"] = await _commentService.GetAll(); return(View(ArticleHelpers.ConvertToDetailsView(articleModel))); }
public async Task <IActionResult> Add(ArticleCommentView result) { var user = await _userManager.GetUserAsync(User); var articleId = result.Article.Id; var commentModel = ArticleHelpers.ConvertCommentToModel(result, user); var comment = await _commentService.Create(commentModel, articleId); return(RedirectToAction("Details", "Article", new { id = articleId })); }
public async Task CreateArticleCategoryTest_ValidData_ExpectSuccess() { //create a test Article var articleCmd = new Conduit.Features.Articles.Create.Command() { Article = new Conduit.Features.Articles.Create.ArticleData() { Title = "Test article dsergiu77", Description = "Description of the test article", Body = "Body of the test article", TagList = new string[] { "tag1", "tag2" } } }; //save it var article = await ArticleHelpers.CreateArticle(this, articleCmd); //create a test category var categoryCmd = new Conduit.Features.Categories.Create.Command() { Category = new Conduit.Features.Categories.Create.CategoryData() { ParentCategory = 0, Name = "TestCategory", Description = "This is a test Category" } }; //save it var createdCategory = await Categories.CategoryHelpers.CreateCategory(this, categoryCmd); //assign the article to the category var createCmd = new Create.Command() { articleCategory = new Domain.ArticleCategory() { ArticleCategoryId = 0, ArticleId = 1, CategoryId = 1, CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now } }; //save the assignment var createdArticleCategory = await ArticleCategoryHelpers.CreateArticleCategory(this, createCmd); //check thats its not null obj Assert.NotNull(createdArticleCategory); //check if it has an ID Assert.NotEqual(0, createdArticleCategory.ArticleCategoryId); }
public async Task <IActionResult> OnPostAsync() { if (!ModelState.IsValid) { return(Page()); } var existingArticle = await _Repo.GetArticleById(Article.Id); Article.ViewCount = existingArticle.ViewCount; Article.Version = existingArticle.Version + 1; //check if the slug already exists in the database. var slug = UrlHelpers.URLFriendly(Article.Topic); if (String.IsNullOrWhiteSpace(slug)) { ModelState.AddModelError("Article.Topic", "The Topic must contain at least one alphanumeric character."); return(Page()); } if (!await _Repo.IsTopicAvailable(slug, Article.Id)) { ModelState.AddModelError("Article.Topic", "This Title already exists."); return(Page()); } var articlesToCreateFromLinks = (await ArticleHelpers.GetArticlesToCreate(_Repo, Article, createSlug: true)) .ToList(); Article.Published = _clock.GetCurrentInstant(); Article.Slug = slug; Article.AuthorId = Guid.Parse(this.User.FindFirstValue(ClaimTypes.NameIdentifier)); Article.AuthorName = User.Identity.Name; if (!string.Equals(Article.Slug, existingArticle.Slug, StringComparison.InvariantCulture)) { await _SlugRepo.AddToHistory(existingArticle.Slug, Article); } //AddNewArticleVersion(); try { await _Repo.Update(Article); } catch (ArticleNotFoundException) { return(new ArticleNotFoundResult()); } if (articlesToCreateFromLinks.Count > 0) { return(RedirectToPage("CreateArticleFromLink", new { id = slug })); } return(Redirect($"/{(Article.Slug == "home-page" ? "" : Article.Slug)}")); }
public ActionResult Article(string id) { if (!String.IsNullOrEmpty(id)) { return(View(new Article() { Description = ArticleHelpers.GetTitle(id), ID = id })); } else { Response.Redirect(getHomeAddress()); return(View()); } }
public ActionResult RequestArticle(string id) { if (id != null) { //Session["ArticleID"] = id; return(View(new Article() { Description = ArticleHelpers.GetTitle(id), ID = id })); } else { Response.Redirect(getHomeAddress()); return(View()); } }
public async Task <IActionResult> Edit(int Id) { //ViewBag.Categories = await _categoryService.GetAll(); //ViewBag.Tags = await _tagService.GetAll(); var articleModel = await _articleService.Get(Id); if (articleModel.User.UserName != User.Identity.Name) { return(RedirectToAction("List", "Article")); } var articleView = ArticleHelpers.ConvertToView(articleModel); return(View(articleView)); }
public async Task <IActionResult> Add(ArticleView result) { if (await _articleService.CheckIfSlugExist(result.Slug)) { ModelState.AddModelError("", "Wpis o podanym linku istnieje"); } if (!ModelState.IsValid) { // 1. Pobieranie listy tagów oraz kategorii ViewBag.Categories = await _categoryService.GetAll(); ViewBag.Tags = await _tagService.GetAll(); return(View(result)); } // 2.Poprawnie zwalidowane post zapisuję do bazy danych // a. Pobranie dodatkowych informacji do artykułu | usera, url strony var user = await _userManager.GetUserAsync(User); var seoSettings = await _seoService.GetSeoSettings(); // b. Utworzenie wpisu var articleModel = ArticleHelpers.ConvertToModel(result, user, seoSettings.MainUrl); var article = await _articleService.Create(articleModel); if (article == false) { return(RedirectToAction("Index", "Admin")); } // TODO: przekieruj na stronę z błędem // c. Zapis zdjęcia var medium = await _cloudService.AddFile(result.FeaturedImg, articleModel); // d. Wygenerowanie taxonomies await _taxonomyService.SaveCategories(await _categoryService.GetCategoriesByNames(result.Categories), articleModel); await _taxonomyService.SaveTags(await _tagService.GetCategoriesByNames(result.Tags), articleModel); return(RedirectToAction("List")); }
public async Task <IActionResult> Edit(int Id) { // 1. Pobieranie listy tagów oraz kategorii ViewBag.Categories = await _categoryService.GetAll(); ViewBag.Tags = await _tagService.GetAll(); var articleModel = await _articleService.Get(Id); // 2. Sprawdzanie czy artykuł należy do użytkownika if (articleModel.User.UserName != User.Identity.Name) { return(RedirectToAction("List", "Article")); } var articleView = ArticleHelpers.ConvertToView(articleModel); return(View(articleView)); }
public async Task <IActionResult> OnPostAsync() { var slug = UrlHelpers.URLFriendly(Article.Topic); if (string.IsNullOrWhiteSpace(slug)) { ModelState.AddModelError("Article.Topic", "The Topic must contain at least one alphanumeric character."); return(Page()); } Article.Slug = slug; Article.AuthorId = Guid.Parse(this.User.FindFirstValue(ClaimTypes.NameIdentifier)); if (!ModelState.IsValid) { return(Page()); } // Check if slug already exist in database Logger.LogWarning($"Creating page with slug: {slug}"); if (await _articleRepo.IsTopicAvailable(slug, 0)) { ModelState.AddModelError("Article.Topic", "This Title already exists."); return(Page()); } Article.Published = _clock.GetCurrentInstant(); Article = await _articleRepo.CreateArticleAndHistory(Article); var articlesToCreateFromLinks = (await ArticleHelpers.GetArticlesToCreate(_articleRepo, Article, createSlug: true)) .ToList(); if (articlesToCreateFromLinks.Count > 0) { return(RedirectToPage("CreateArticleFromLink", new { id = slug })); } return(Redirect($"/Articles/{Article.Slug}")); }
public async Task <IActionResult> Edit(ArticleView result) { var article = await _articleService.Get(result.Id); if (result.Slug != article.Slug) { //if(await _articleService.CheckIfSlugExist(result.Slug)) //{ // ModelState.AddModelError("", "Artykuł o podanym linku nie istnieje"); //} } //if(!ModelState.IsValid) //{ // ViewBag.Categories = await _categoryService.GetAll(); // ViewBag.Tags = await _tagService.GetAll(); // return View(result); //} if (result.FeaturedImg != null) { if (article.Image != null) { _cloudinaryService.DeleteFile(article.Image.Id); } var photo = await _cloudinaryService.AddFile(result.FeaturedImg); article.Image = photo; } await _articleService.Update(ArticleHelpers.MergeViewWithModel(article, result, "https://theraphosidae.pl")); //await _taxonomyService.Delete(result.Id); //await _taxonomyService.SaveCategories(await _categoryService.GetCategoriesByName(result.Categories), article); //await _taxonomyService.SaveTags(await _tagService.GetCategoriesByNames(result.Tags), article); return(RedirectToAction("List")); }
public async Task <IActionResult> OnGetAsync(string id) { if (id == null) { return(NotFound()); } Article = await _articleRepo.GetArticleBySlug(id); if (Article == null) { return(new ArticleNotFoundResult()); } LinksToCreate = (await ArticleHelpers.GetArticlesToCreate(_articleRepo, Article)).ToList(); if (LinksToCreate.Count == 0) { return(Redirect($"/{(Article.Slug == "home-page" ? "" : Article.Slug)}")); } return(Page()); }
private static async Task MainAsync(string[] args) { // You may adjust these values to experiment with different compute resource scenarios. const string nodeSize = "standard_d1_v2"; const int nodeCount = 1; const int taskSlotsPerNode = 4; // Adjust the task count to experiment with different list operation query durations const int taskCount = 5000; const string poolId = "EfficientListQueriesSamplePool"; const string jobId = "EfficientListQueriesSampleJob"; var accountSettings = SampleHelpers.LoadAccountSettings(); // Set up the credentials required by the BatchClient. Configure your AccountSettings in the // Microsoft.Azure.Batch.Samples.Common project within this solution. BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials( accountSettings.BatchServiceUrl, accountSettings.BatchAccountName, accountSettings.BatchAccountKey); using (BatchClient batchClient = BatchClient.Open(cred)) { // Create a CloudPool, or obtain an existing pool with the specified ID CloudPool pool = await ArticleHelpers.CreatePoolIfNotExistAsync( batchClient, poolId, nodeSize, nodeCount, taskSlotsPerNode); // Create a CloudJob, or obtain an existing job with the specified ID CloudJob job = await ArticleHelpers.CreateJobIfNotExistAsync(batchClient, poolId, jobId); // Configure the tasks we'll be querying. Each task simply echoes the node's // name and then exits. We create "large" tasks by setting an environment // variable for each that is 2048 bytes in size. This is done simply to // increase response time when querying the batch service to more clearly // demonstrate query durations. List <CloudTask> tasks = new List <CloudTask>(); List <EnvironmentSetting> environmentSettings = new List <EnvironmentSetting>(); environmentSettings.Add(new EnvironmentSetting("BIGENV", GetBigString(2048))); for (int i = 1; i < taskCount + 1; i++) { string taskId = "task" + i.ToString().PadLeft(5, '0'); string taskCommandLine = "cmd /c echo %COMPUTERNAME%"; CloudTask task = new CloudTask(taskId, taskCommandLine); task.EnvironmentSettings = environmentSettings; tasks.Add(task); } Console.WriteLine(); Console.WriteLine("Adding {0} tasks to job {1}...", taskCount, job.Id); Stopwatch stopwatch = Stopwatch.StartNew(); // Add the tasks in one API call as opposed to a separate AddTask call for each. Bulk task submission // helps to ensure efficient underlying API calls to the Batch service. await batchClient.JobOperations.AddTaskAsync(job.Id, tasks); stopwatch.Stop(); Console.WriteLine("{0} tasks added in {1}, hit ENTER to query tasks...", taskCount, stopwatch.Elapsed); Console.ReadLine(); Console.WriteLine(); stopwatch.Reset(); // Obtain the tasks, specifying different detail levels to demonstrate limiting the number of tasks returned // and the amount of data returned for each. If your job tasks number in the thousands or have "large" properties // (such as our big environment variable), specifying a DetailLevel is important in reducing the amount of data // transferred, lowering your query response times (potentially greatly). // Get a subset of the tasks based on different task states ODATADetailLevel detail = new ODATADetailLevel(); detail.FilterClause = "state eq 'active'"; detail.SelectClause = "id,state"; await QueryTasksAsync(batchClient, job.Id, detail); detail.FilterClause = "state eq 'running'"; await QueryTasksAsync(batchClient, job.Id, detail); detail.FilterClause = "state eq 'completed'"; await QueryTasksAsync(batchClient, job.Id, detail); // Get all tasks, but limit the properties returned to task id and state only detail.FilterClause = null; detail.SelectClause = "id,state"; await QueryTasksAsync(batchClient, job.Id, detail); // Get all tasks, include id and state, also include the inflated environment settings property detail.SelectClause = "id,state,environmentSettings"; await QueryTasksAsync(batchClient, job.Id, detail); // Get all tasks, include all standard properties, and expand the statistics detail.ExpandClause = "stats"; detail.SelectClause = null; await QueryTasksAsync(batchClient, job.Id, detail); Console.WriteLine(); Console.WriteLine("Done!"); Console.WriteLine(); // Clean up the resources we've created in the Batch account Console.WriteLine("Delete job? [yes] no"); string response = Console.ReadLine().ToLower(); if (response != "n" && response != "no") { await batchClient.JobOperations.DeleteJobAsync(job.Id); } Console.WriteLine("Delete pool? [yes] no"); response = Console.ReadLine().ToLower(); if (response != "n" && response != "no") { await batchClient.PoolOperations.DeletePoolAsync(pool.Id); } } }
public static void Main(string[] args) { const int taskCount = 5000; const string poolId = "poolEffQuery"; const string jobId = "jobEffQuery"; // Set up the credentials required by the BatchClient. Configure your AccountSettings in the // Microsoft.Azure.Batch.Samples.Common project within this solution. BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(AccountSettings.Default.BatchServiceUrl, AccountSettings.Default.BatchAccountName, AccountSettings.Default.BatchAccountKey); using (BatchClient batchClient = BatchClient.Open(cred)) { // Create a CloudPool, or obtain an existing pool with the specified ID CreatePool(batchClient, poolId).Wait(); CloudPool pool = batchClient.PoolOperations.GetPool(poolId); // Create a CloudJob, or obtain an existing job with the specified ID CloudJob job = ArticleHelpers.CreateJobAsync(batchClient, poolId, jobId).Result; // Configure the tasks we'll be querying. Each task simply echoes the node's // name and then exits. We create "large" tasks by setting an environment // variable for each that is 2048 bytes in size. This is done simply to // increase response time when querying the batch service to more clearly // demonstrate query durations. List <CloudTask> tasks = new List <CloudTask>(); List <EnvironmentSetting> environmentSettings = new List <EnvironmentSetting>(); environmentSettings.Add(new EnvironmentSetting("BIGENV", GetBigString(2048))); for (int i = 1; i < taskCount + 1; i++) { string taskId = "task" + i.ToString().PadLeft(5, '0'); string taskCommandLine = "cmd /c echo %COMPUTERNAME%"; CloudTask task = new CloudTask(taskId, taskCommandLine); task.EnvironmentSettings = environmentSettings; tasks.Add(task); } Console.WriteLine(); Console.WriteLine("Adding {0} tasks to job {1}...", taskCount, job.Id); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); // To reduce the chances of hitting Batch service throttling limits, we add the tasks in // one API call as opposed to a separate AddTask call for each. This is crucial if you // are adding many tasks to your jobs. batchClient.JobOperations.AddTask(job.Id, tasks); stopwatch.Stop(); Console.WriteLine("{0} tasks added in {1}, hit ENTER to query tasks...", taskCount, stopwatch.Elapsed); Console.ReadLine(); Console.WriteLine(); stopwatch.Reset(); // Obtain the tasks, specifying different detail levels to demonstrate limiting the number of tasks returned // and the amount of data returned for each. If your job tasks number in the thousands or have "large" properties // (such as our big environment variable), specifying a DetailLevel is important in reducing the amount of data // transferred, lowering your query response times (potentially greatly). // Get a subset of the tasks based on different task states ODATADetailLevel detail = new ODATADetailLevel(); detail.FilterClause = "state eq 'active'"; detail.SelectClause = "id,state"; QueryTasks(batchClient, job.Id, detail); detail.FilterClause = "state eq 'running'"; QueryTasks(batchClient, job.Id, detail); detail.FilterClause = "state eq 'completed'"; QueryTasks(batchClient, job.Id, detail); // Get all tasks, but limit the properties returned to task id and state only detail.FilterClause = null; detail.SelectClause = "id,state"; QueryTasks(batchClient, job.Id, detail); // Get all tasks, include id and state, also include the inflated environment settings property detail.SelectClause = "id,state,environmentSettings"; QueryTasks(batchClient, job.Id, detail); // Get all tasks, include all standard properties, and expand the statistics detail.ExpandClause = "stats"; detail.SelectClause = null; QueryTasks(batchClient, job.Id, detail); Console.WriteLine(); Console.WriteLine("Sample complete, hit ENTER to continue..."); Console.ReadLine(); // Clean up the resources we've created in the Batch account Console.WriteLine("Delete job? [yes] no"); string response = Console.ReadLine().ToLower(); if (response != "n" && response != "no") { batchClient.JobOperations.DeleteJob(job.Id); } Console.WriteLine("Delete pool? [yes] no"); response = Console.ReadLine().ToLower(); if (response != "n" && response != "no") { batchClient.PoolOperations.DeletePool(pool.Id); } } }
private static async Task MainAsync(string[] args) { const string poolId = "JobPrepReleaseSamplePool"; const string jobId = "JobPrepReleaseSampleJob"; // Location of the file that the job tasks will work with, a text file in the // node's "shared" directory. const string taskOutputFile = "%AZ_BATCH_NODE_SHARED_DIR%\\job_prep_and_release.txt"; // The job prep task will write the node ID to the text file in the shared directory const string jobPrepCmdLine = "cmd /c echo %AZ_BATCH_NODE_ID% tasks: >" + taskOutputFile; // Each task then echoes its ID to the same text file const string taskCmdLine = "cmd /c echo %AZ_BATCH_TASK_ID% >> " + taskOutputFile; // The job release task will then delete the text file from the shared directory const string jobReleaseCmdLine = "cmd /c del " + taskOutputFile; // Configure your AccountSettings in the Microsoft.Azure.Batch.Samples.Common project within this solution BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(AccountSettings.Default.BatchServiceUrl, AccountSettings.Default.BatchAccountName, AccountSettings.Default.BatchAccountKey); // Initialize the BatchClient for access to your Batch account using (BatchClient batchClient = await BatchClient.OpenAsync(cred)) { // Create a CloudPool (or obtain an existing pool with the specified ID) CloudPool pool = await ArticleHelpers.CreatePoolIfNotExistAsync(batchClient, poolId, "small", 2, 1); // Create a CloudJob (or obtain an existing job with the specified ID) CloudJob job = await SampleHelpers.GetJobIfExistAsync(batchClient, jobId); if (job == null) { Console.WriteLine("Job {0} not found, creating...", jobId); CloudJob unboundJob = batchClient.JobOperations.CreateJob(jobId, new PoolInformation() { PoolId = poolId }); // Configure and assign the job preparation task unboundJob.JobPreparationTask = new JobPreparationTask { CommandLine = jobPrepCmdLine }; // Configure and assign the job release task unboundJob.JobReleaseTask = new JobReleaseTask { CommandLine = jobReleaseCmdLine }; await unboundJob.CommitAsync(); // Get the bound version of the job with all of its properties populated job = await batchClient.JobOperations.GetJobAsync(jobId); } // Create the tasks that the job will execute List <CloudTask> tasks = new List <CloudTask>(); for (int i = 1; i <= 8; i++) { string taskId = "task" + i.ToString().PadLeft(3, '0'); string taskCommandLine = taskCmdLine; CloudTask task = new CloudTask(taskId, taskCommandLine); tasks.Add(task); } // Add the tasks in one API call as opposed to a separate AddTask call for each. Bulk task // submission helps to ensure efficient underlying API calls to the Batch service. Console.WriteLine("Submitting tasks and awaiting completion..."); await batchClient.JobOperations.AddTaskAsync(job.Id, tasks); // Wait for the tasks to complete before proceeding. The long timeout here is to allow time // for the nodes within the pool to be created and started if the pool had not yet been created. await batchClient.Utilities.CreateTaskStateMonitor().WhenAll( job.ListTasks(), TaskState.Completed, TimeSpan.FromMinutes(30)); Console.WriteLine("All tasks completed."); Console.WriteLine(); // Print the contents of the shared text file modified by the job preparation and other tasks. ODATADetailLevel nodeDetail = new ODATADetailLevel(selectClause: "id, state"); IPagedEnumerable <ComputeNode> nodes = batchClient.PoolOperations.ListComputeNodes(pool.Id, nodeDetail); await nodes.ForEachAsync(async (node) => { // Check to ensure that the node is Idle before attempting to pull the text file. // If the pool was just created, there is a chance that another node completed all // of the tasks prior to the other node(s) completing their startup procedure. if (node.State == ComputeNodeState.Idle) { NodeFile sharedTextFile = await node.GetNodeFileAsync("shared\\job_prep_and_release.txt"); Console.WriteLine("Contents of {0} on {1}:", sharedTextFile.Name, node.Id); Console.WriteLine("-------------------------------------------"); Console.WriteLine(await sharedTextFile.ReadAsStringAsync()); } }); // Terminate the job to mark it as Completed; this will initiate the Job Release Task on any node // that executed job tasks. Note that the Job Release Task is also executed when a job is deleted, // thus you need not call Terminate if you typically delete your jobs upon task completion. await batchClient.JobOperations.TerminateJobAsync(job.Id); // Wait for the job to reach state "Completed." Note that this wait is not typically necessary in // production code, but is done here to enable the checking of the release tasks exit code below. await ArticleHelpers.WaitForJobToReachStateAsync(batchClient, job.Id, JobState.Completed, TimeSpan.FromMinutes(2)); // Print the exit codes of the prep and release tasks by obtaining their execution info List <JobPreparationAndReleaseTaskExecutionInformation> prepReleaseInfo = await batchClient.JobOperations.ListJobPreparationAndReleaseTaskStatus(job.Id).ToListAsync(); foreach (JobPreparationAndReleaseTaskExecutionInformation info in prepReleaseInfo) { Console.WriteLine(); Console.WriteLine("{0}: ", info.ComputeNodeId); // If no tasks were scheduled to run on the node, the JobPreparationTaskExecutionInformation will be null if (info.JobPreparationTaskExecutionInformation != null) { Console.WriteLine(" Prep task exit code: {0}", info.JobPreparationTaskExecutionInformation.ExitCode); } // If no tasks were scheduled to run on the node, the JobReleaseTaskExecutionInformation will be null if (info.JobReleaseTaskExecutionInformation != null) { Console.WriteLine(" Release task exit code: {0}", info.JobReleaseTaskExecutionInformation.ExitCode); } } // Clean up the resources we've created in the Batch account Console.WriteLine(); Console.WriteLine("Delete job? [yes] no"); string response = Console.ReadLine().ToLower(); if (response != "n" && response != "no") { // Note that deleting the job will execute the job release task if the job was not previously terminated await batchClient.JobOperations.DeleteJobAsync(job.Id); } Console.WriteLine("Delete pool? [yes] no"); response = Console.ReadLine(); if (response != "n" && response != "no") { await batchClient.PoolOperations.DeletePoolAsync(pool.Id); } } }
private static async Task MainAsync(string[] args) { // You may adjust these values to experiment with different compute resource scenarios. const string nodeSize = "small"; const int nodeCount = 4; const int maxTasksPerNode = 4; const int taskCount = 32; // Ensure there are enough tasks to help avoid hitting some timeout conditions below int minimumTaskCount = nodeCount * maxTasksPerNode * 2; if (taskCount < minimumTaskCount) { Console.WriteLine("You must specify at least two tasks per node core for this sample ({0} tasks in this configuration).", minimumTaskCount); Console.WriteLine(); // Not enough tasks, exit the application return; } // In this sample, the tasks simply ping localhost on the compute nodes; adjust these // values to simulate variable task duration const int minPings = 30; const int maxPings = 60; const string poolId = "ParallelTasksSamplePool"; const string jobId = "ParallelTasksSampleJob"; // Amount of time to wait before timing out (potentially) long-running tasks TimeSpan longTaskDurationLimit = TimeSpan.FromMinutes(30); // Set up access to your Batch account with a BatchClient. Configure your AccountSettings in the // Microsoft.Azure.Batch.Samples.Common project within this solution. BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(AccountSettings.Default.BatchServiceUrl, AccountSettings.Default.BatchAccountName, AccountSettings.Default.BatchAccountKey); using (BatchClient batchClient = await BatchClient.OpenAsync(cred)) { // Create a CloudPool, or obtain an existing pool with the specified ID CloudPool pool = await ArticleHelpers.CreatePoolIfNotExistAsync(batchClient, poolId, nodeSize, nodeCount, maxTasksPerNode); // Create a CloudJob, or obtain an existing pool with the specified ID CloudJob job = await ArticleHelpers.CreateJobIfNotExistAsync(batchClient, poolId, jobId); // The job's tasks ping localhost a random number of times between minPings and maxPings. // Adjust the minPings/maxPings values above to experiment with different task durations. Random rand = new Random(); List <CloudTask> tasks = new List <CloudTask>(); for (int i = 1; i <= taskCount; i++) { string taskId = "task" + i.ToString().PadLeft(3, '0'); string taskCommandLine = "ping -n " + rand.Next(minPings, maxPings + 1).ToString() + " localhost"; CloudTask task = new CloudTask(taskId, taskCommandLine); tasks.Add(task); } // Pause execution until the pool is steady and its compute nodes are ready to accept jobs. // NOTE: Such a pause is not necessary within your own code. Tasks can be added to a job at any point and will be // scheduled to execute on a compute node as soon any node has reached Idle state. Because the focus of this sample // is the demonstration of running tasks in parallel on multiple compute nodes, we wait for all compute nodes to // complete initialization and reach the Idle state in order to maximize the number of compute nodes available for // parallelization. await ArticleHelpers.WaitForPoolToReachStateAsync(batchClient, pool.Id, AllocationState.Steady, longTaskDurationLimit); await ArticleHelpers.WaitForNodesToReachStateAsync(batchClient, pool.Id, ComputeNodeState.Idle, longTaskDurationLimit); // Add the tasks in one API call as opposed to a separate AddTask call for each. Bulk task submission // helps to ensure efficient underlying API calls to the Batch service. await batchClient.JobOperations.AddTaskAsync(job.Id, tasks); // Pause again to wait until *all* nodes are running tasks await ArticleHelpers.WaitForNodesToReachStateAsync(batchClient, pool.Id, ComputeNodeState.Running, TimeSpan.FromMinutes(2)); Stopwatch stopwatch = Stopwatch.StartNew(); // Print out task assignment information. Console.WriteLine(); await GettingStartedCommon.PrintNodeTasksAsync(batchClient, pool.Id); Console.WriteLine(); // Pause execution while we wait for all of the tasks to complete Console.WriteLine("Waiting for task completion..."); Console.WriteLine(); try { await batchClient.Utilities.CreateTaskStateMonitor().WhenAll( job.ListTasks(), TaskState.Completed, longTaskDurationLimit); } catch (TimeoutException e) { Console.WriteLine(e.ToString()); } stopwatch.Stop(); // Obtain the tasks, specifying a detail level to limit the number of properties returned for each task. // If you have a large number of tasks, specifying a DetailLevel is extremely important in reducing the // amount of data transferred, lowering your query response times in increasing performance. ODATADetailLevel detail = new ODATADetailLevel(selectClause: "id,commandLine,nodeInfo,state"); IPagedEnumerable <CloudTask> allTasks = batchClient.JobOperations.ListTasks(job.Id, detail); // Get a collection of the completed tasks sorted by the compute nodes on which they executed List <CloudTask> completedTasks = allTasks .Where(t => t.State == TaskState.Completed) .OrderBy(t => t.ComputeNodeInformation.ComputeNodeId) .ToList(); // Print the completed task information Console.WriteLine(); Console.WriteLine("Completed tasks:"); string lastNodeId = string.Empty; foreach (CloudTask task in completedTasks) { if (!string.Equals(lastNodeId, task.ComputeNodeInformation.ComputeNodeId)) { Console.WriteLine(); Console.WriteLine(task.ComputeNodeInformation.ComputeNodeId); } lastNodeId = task.ComputeNodeInformation.ComputeNodeId; Console.WriteLine("\t{0}: {1}", task.Id, task.CommandLine); } // Get a collection of the uncompleted tasks which may exist if the TaskMonitor timeout was hit List <CloudTask> uncompletedTasks = allTasks .Where(t => t.State != TaskState.Completed) .OrderBy(t => t.Id) .ToList(); // Print a list of uncompleted tasks, if any Console.WriteLine(); Console.WriteLine("Uncompleted tasks:"); Console.WriteLine(); if (uncompletedTasks.Any()) { foreach (CloudTask task in uncompletedTasks) { Console.WriteLine("\t{0}: {1}", task.Id, task.CommandLine); } } else { Console.WriteLine("\t<none>"); } // Print some summary information Console.WriteLine(); Console.WriteLine(" Nodes: " + nodeCount); Console.WriteLine(" Node size: " + nodeSize); Console.WriteLine("Max tasks per node: " + pool.MaxTasksPerComputeNode); Console.WriteLine(" Tasks: " + tasks.Count); Console.WriteLine(" Duration: " + stopwatch.Elapsed); Console.WriteLine(); Console.WriteLine("Done!"); Console.WriteLine(); // Clean up the resources we've created in the Batch account Console.WriteLine("Delete job? [yes] no"); string response = Console.ReadLine().ToLower(); if (response != "n" && response != "no") { await batchClient.JobOperations.DeleteJobAsync(job.Id); } Console.WriteLine("Delete pool? [yes] no"); response = Console.ReadLine(); if (response != "n" && response != "no") { await batchClient.PoolOperations.DeletePoolAsync(pool.Id); } } }