Skip to content

Commit

Permalink
Enhance the way we retrieve the build history.
Browse files Browse the repository at this point in the history
  • Loading branch information
steffen-wilke committed Aug 26, 2019
1 parent 02c4c79 commit af387d0
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 51 deletions.
7 changes: 7 additions & 0 deletions src/Soloplan.WhatsON.Jenkins.Tests/FakeJenkinsApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
namespace Soloplan.WhatsON.Jenkins.Tests
{
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Soloplan.WhatsON.Jenkins;
using Soloplan.WhatsON.Jenkins.Model;
using Soloplan.WhatsON.Model;

public class FakeJenkinsApi : IJenkinsApi
{
Expand Down Expand Up @@ -52,6 +54,11 @@ public async Task<JenkinsBuild> GetJenkinsBuild(JenkinsConnector connector, int

return eventArgs.Result;
}

public Task<IList<JenkinsBuild>> GetBuilds(JenkinsConnector connector, CancellationToken token, int @from = 0, int to = Connector.MaxSnapshots)
{
throw new NotImplementedException();
}
}

public class FakeApiEventArgs : EventArgs
Expand Down
4 changes: 4 additions & 0 deletions src/Soloplan.WhatsON.Jenkins/IJenkinsApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@

namespace Soloplan.WhatsON.Jenkins
{
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Soloplan.WhatsON.Jenkins.Model;
using Soloplan.WhatsON.Model;

/// <summary>
/// Interface defining API for Jenkins.
Expand All @@ -32,5 +34,7 @@ public interface IJenkinsApi
/// <param name="token">Cancellation token.</param>
/// <returns>Information about specific build. <seealso cref="JenkinsBuild"/>.</returns>
Task<JenkinsBuild> GetJenkinsBuild(JenkinsConnector connector, int buildNumber, CancellationToken token);

Task<IList<JenkinsBuild>> GetBuilds(JenkinsConnector connector, CancellationToken token, int from = 0, int to = Connector.MaxSnapshots);
}
}
18 changes: 18 additions & 0 deletions src/Soloplan.WhatsON.Jenkins/JenkinsAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@
namespace Soloplan.WhatsON.Jenkins
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using Newtonsoft.Json;
using NLog;
using Soloplan.WhatsON.Jenkins.Model;
using Soloplan.WhatsON.Model;

public class JenkinsApi : IJenkinsApi
{
Expand Down Expand Up @@ -55,5 +58,20 @@ public async Task<JenkinsBuild> GetJenkinsBuild(JenkinsConnector connector, int
log.Trace("Querying build: {jobRequest}", buildRequest);
return await SerializationHelper.GetJsonModel<JenkinsBuild>(buildRequest, token);
}

public async Task<IList<JenkinsBuild>> GetBuilds(JenkinsConnector connector, CancellationToken token, int from = 0, int to = Connector.MaxSnapshots)
{
var address = connector.Address;
var projectName = connector.GetProject();

var buildsRequest = $"{address.Trim('/')}/job/{projectName.Trim('/')}/api/json?tree=builds[{JenkinsBuild.RequestProperties}]{{{from},{to}}}";
var builds = await SerializationHelper.GetJsonModel<JenkinsBuilds>(buildsRequest, token);
if (builds == null || builds.Builds == null)
{
return new List<JenkinsBuild>();
}

return builds.Builds;
}
}
}
56 changes: 6 additions & 50 deletions src/Soloplan.WhatsON.Jenkins/JenkinsConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ public JenkinsConnector(ConnectorConfiguration configuration, IJenkinsApi api)

public string Project => this.GetProject();

private JenkinsStatus PreviousCheckStatus { get; set; }

/// <summary>
/// Gets the project.
/// </summary>
Expand All @@ -78,64 +76,22 @@ protected override async Task ExecuteQuery(CancellationToken cancellationToken,

var latestBuild = await this.api.GetJenkinsBuild(this, job.LastBuild.Number, cancellationToken);
this.CurrentStatus = CreateStatus(latestBuild);
if (this.Snapshots.Count == 0 && job.FirstBuild.Number < job.LastBuild.Number)
if (this.Snapshots.Count == 0 && job.LastBuild.Number > 1)
{
var startBuildNumber = latestBuild.Building ? latestBuild.Number - 1 : latestBuild.Number;
var lastHistoryBuild = Math.Max(startBuildNumber - MaxSnapshots + 1, 0);
lastHistoryBuild = Math.Max(lastHistoryBuild, job.FirstBuild.Number);
log.Debug("Retrieving history from the server for builds {builds}", new { StartBuild = lastHistoryBuild, EndBuild = startBuildNumber - 1 });

JenkinsStatus buildStatus = null;
for (int i = lastHistoryBuild; i <= startBuildNumber; i++)
foreach (var build in await this.api.GetBuilds(this, cancellationToken, 1, MaxSnapshots + 1))
{
buildStatus = CreateStatus(await this.api.GetJenkinsBuild(this, i, cancellationToken));
log.Debug("Retrieved status {buildStatus}", buildStatus);
var buildStatus = CreateStatus(build);
this.AddSnapshot(buildStatus);
}

this.PreviousCheckStatus = buildStatus;
}

if (this.PreviousCheckStatus != null && this.CurrentStatus is JenkinsStatus currentStatus)
// push current state to the snapshots because it's done building
if (this.ShouldTakeSnapshot(this.CurrentStatus))
{
if (currentStatus.BuildNumber - this.PreviousCheckStatus.BuildNumber > 1)
{
var start = this.PreviousCheckStatus.BuildNumber + 1;
for (int i = start; i < currentStatus.BuildNumber; i++)
{
var buildStatus = CreateStatus(await this.api.GetJenkinsBuild(this, i, cancellationToken));
if (this.ShouldTakeSnapshot(buildStatus))
{
this.AddSnapshot(buildStatus);
}
}
}
this.AddSnapshot(this.CurrentStatus);
}
}

protected override bool ShouldTakeSnapshot(Status status)
{
log.Trace("Checking if snapshot should be taken...");
if (status is JenkinsStatus currentStatus)
{
if (this.PreviousCheckStatus != null)
{
if (status.State != ObservationState.Running && (status.State != this.PreviousCheckStatus.State || this.PreviousCheckStatus.BuildNumber != currentStatus.BuildNumber))
{
log.Debug("Snapshot should be taken. {stat}", new { this.PreviousCheckStatus, CurrentStatus = currentStatus });
this.PreviousCheckStatus = currentStatus;
return true;
}
}
else
{
this.PreviousCheckStatus = currentStatus;
}
}

return false;
}

private static JenkinsStatus CreateStatus(JenkinsBuild latestBuild)
{
var newStatus = new JenkinsStatus(GetState(latestBuild))
Expand Down
16 changes: 16 additions & 0 deletions src/Soloplan.WhatsON.Jenkins/Model/JenkinsBuilds.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="JenkinsBuilds.cs" company="Soloplan GmbH">
// Copyright (c) Soloplan GmbH. All rights reserved.
// Licensed under the MIT License. See License-file in the project root for license information.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace Soloplan.WhatsON.Jenkins.Model
{
using System.Collections.Generic;

public class JenkinsBuilds
{
public IList<JenkinsBuild> Builds { get; set; }
}
}
10 changes: 9 additions & 1 deletion src/Soloplan.WhatsON/Model/Connector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public void AddSnapshot(Status status)
while (this.Snapshots.Count >= MaxSnapshots)
{
log.Debug("Max number of snapshots exceeded. Dequeuing snapshot.", new { Name = this.ConnectorConfiguration.Name, CurrentStatus = this.CurrentStatus });
this.Snapshots.RemoveAt(0);
this.Snapshots.RemoveAt(this.Snapshots.Count - 1); // remove the end of the list because we're sortring by age
}

this.Snapshots.Add(new Snapshot(status));
Expand Down Expand Up @@ -131,6 +131,14 @@ public override string ToString()

protected virtual bool ShouldTakeSnapshot(Status status)
{
log.Trace("Checking if snapshot should be taken...");

if (status.State != ObservationState.Running && this.Snapshots.All(x => x.Status.BuildNumber != status.BuildNumber))
{
log.Debug("Snapshot should be taken. {stat}", new { CurrentStatus = status });
return true;
}

return false;
}
}
Expand Down

0 comments on commit af387d0

Please sign in to comment.