Skip to content

Commit 03466ae

Browse files
authored
Merge pull request #12 from fossapps/11-disallow-stoping-stopped-run
fix(featureRuns): disallow stopping stopped run
2 parents 7ddae9f + 1d210e0 commit 03466ae

File tree

5 files changed

+118
-3
lines changed

5 files changed

+118
-3
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System;
2+
3+
namespace Feature.Manager.Api.FeatureRuns.Exceptions
4+
{
5+
public class FeatureRunAlreadyStoppedException : Exception
6+
{
7+
8+
}
9+
}

Feature.Manager.Api/FeatureRuns/FeatureRunService.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public async Task<FeatureRun> CreateFeatureRun(CreateFeatureRunRequest request)
3434
try
3535
{
3636
var runs = await _featureRunRepository.GetRunsForFeatureByFeatId(request.FeatId);
37-
if (runs.Any(x => x.EndAt == null))
37+
if (runs.Any(x => x.EndAt == null || x.StopResult == StopResult.AllB))
3838
{
3939
throw new FeatureAlreadyRunningException();
4040
}
@@ -82,13 +82,22 @@ public async Task<FeatureRun> StopFeatureRun(StopFeatureRunRequest request)
8282
throw new FeatureRunNotFoundException();
8383
}
8484

85+
if (result.EndAt?.ToUniversalTime() <= DateTime.UtcNow && result.StopResult != StopResult.AllB)
86+
{
87+
throw new FeatureRunAlreadyStoppedException();
88+
}
89+
8590
if (!Enum.TryParse(request.StopResult, out StopResult stopResult))
8691
{
8792
throw new InvalidStopResultValueException();
8893
}
8994

9095
return await _featureRunRepository.StopFeatureRun(request);
9196
}
97+
catch (FeatureRunAlreadyStoppedException)
98+
{
99+
throw;
100+
}
92101
catch (FeatureRunNotFoundException)
93102
{
94103
throw;

Feature.Manager.Api/FeatureRuns/FeatureRunsController.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,13 @@ public async Task<IActionResult> StopRun(StopFeatureRunRequest request)
119119
var result = await _featureRunService.StopFeatureRun(request);
120120
return Ok(result);
121121
}
122+
catch (FeatureRunAlreadyStoppedException)
123+
{
124+
return BadRequest(new ProblemDetails
125+
{
126+
Title = "Run Already stopped"
127+
});
128+
}
122129
catch (InvalidStopResultValueException)
123130
{
124131
return BadRequest(new ProblemDetails

Feature.Manager.UnitTest/FeatureRuns/FeatureRunCreateServiceTest.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ public void Setup()
7575
{
7676
MakeFeatureRun(StopResult.AllB, "APP-5", DateTime.Now.Subtract(TimeSpan.FromHours(12)))
7777
});
78+
mock.Setup(x => x.GetRunsForFeatureByFeatId("APP-6")).ReturnsAsync(new List<FeatureRun>
79+
{
80+
MakeFeatureRun(StopResult.AllA, "APP-6", DateTime.Now.Subtract(TimeSpan.FromHours(12)))
81+
});
7882
mock.Setup(x => x.GetRunsForFeatureByFeatId("APP-19")).ReturnsAsync(new List<FeatureRun>());
7983
_mock = mock;
8084
var featureRepository = new Mock<IFeatureRepository>();
@@ -116,19 +120,35 @@ public async Task TestCannotCreateNewRunIfARunIsAlreadyRunning()
116120
StartAt = DateTime.Now,
117121
FeatId = "APP-2"
118122
}));
123+
Assert.ThrowsAsync<FeatureAlreadyRunningException>(() => _featureRunService.CreateFeatureRun(
124+
new CreateFeatureRunRequest
125+
{
126+
Allocation = 100,
127+
EndAt = DateTime.Now.Add(TimeSpan.FromDays(20)),
128+
StartAt = DateTime.Now,
129+
FeatId = "APP-5"
130+
}));
119131
}
120132

121133
[Test]
122134
public async Task TestCreatesNewRunWhenNoFeaturesAreRunning()
123135
{
124-
var result = await _featureRunService.CreateFeatureRun(new CreateFeatureRunRequest
136+
var app3 = await _featureRunService.CreateFeatureRun(new CreateFeatureRunRequest
125137
{
126138
Allocation = 100,
127139
EndAt = DateTime.Now.Add(TimeSpan.FromDays(20)),
128140
StartAt = DateTime.Now,
129141
FeatId = "APP-3"
130142
});
131-
Assert.NotNull(result);
143+
var app6 = await _featureRunService.CreateFeatureRun(new CreateFeatureRunRequest
144+
{
145+
Allocation = 100,
146+
EndAt = DateTime.Now.Add(TimeSpan.FromDays(20)),
147+
StartAt = DateTime.Now,
148+
FeatId = "APP-6"
149+
});
150+
Assert.NotNull(app3);
151+
Assert.NotNull(app6);
132152
}
133153

134154
[Test]

Feature.Manager.UnitTest/FeatureRuns/FeatureRunServiceTest.cs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,46 @@ public void Setup()
3838
FeatId = "APP-1",
3939
RunToken = "RAND-UUID-TOKEN",
4040
});
41+
mock.Setup(x => x.GetById("stopped-run-all-b")).ReturnsAsync(new FeatureRun
42+
{
43+
Allocation = 100,
44+
Id = "stopped-run-all-b",
45+
EndAt = DateTime.Now.Subtract(TimeSpan.FromSeconds(5)),
46+
StartAt = DateTime.Now.Subtract(TimeSpan.FromDays(2)),
47+
StopResult = StopResult.AllB,
48+
FeatId = "APP-1",
49+
RunToken = "RAND-UUID-TOKEN",
50+
});
51+
mock.Setup(x => x.GetById("stopped-run-changed-settings")).ReturnsAsync(new FeatureRun
52+
{
53+
Allocation = 100,
54+
Id = "stopped-run-changed-settings",
55+
EndAt = DateTime.Now.Subtract(TimeSpan.FromSeconds(5)),
56+
StartAt = DateTime.Now.Subtract(TimeSpan.FromDays(2)),
57+
StopResult = StopResult.ChangeSettings,
58+
FeatId = "APP-1",
59+
RunToken = "RAND-UUID-TOKEN",
60+
});
61+
mock.Setup(x => x.GetById("stopped-run-all-a")).ReturnsAsync(new FeatureRun
62+
{
63+
Allocation = 100,
64+
Id = "stopped-run-all-a",
65+
EndAt = DateTime.Now.Subtract(TimeSpan.FromSeconds(5)),
66+
StopResult = StopResult.AllA,
67+
StartAt = DateTime.Now.Subtract(TimeSpan.FromDays(2)),
68+
FeatId = "APP-1",
69+
RunToken = "RAND-UUID-TOKEN",
70+
});
71+
mock.Setup(x => x.GetById("stopped-run-removed-from-code")).ReturnsAsync(new FeatureRun
72+
{
73+
Allocation = 100,
74+
Id = "stopped-run-removed-from-code",
75+
EndAt = DateTime.Now.Subtract(TimeSpan.FromSeconds(5)),
76+
StopResult = StopResult.Removed,
77+
StartAt = DateTime.Now.Subtract(TimeSpan.FromDays(2)),
78+
FeatId = "APP-1",
79+
RunToken = "RAND-UUID-TOKEN",
80+
});
4181
mock.Setup(x => x.GetById("RUN-UUID-3")).ThrowsAsync(new InvalidCastException());
4282
mock.Setup(x => x.StopFeatureRun(It.IsAny<StopFeatureRunRequest>())).ReturnsAsync(
4383
(StopFeatureRunRequest request) =>
@@ -199,5 +239,35 @@ public async Task TestGetRunningFeaturesHandlesException()
199239
var systemUnderTest = new FeatureRunService(mock.Object, null);
200240
Assert.ThrowsAsync<UnknownDbException>(() => systemUnderTest.GetRunningFeatures());
201241
}
242+
243+
[Test]
244+
public async Task StoppedRunsCantBeStoppedFurther()
245+
{
246+
Assert.ThrowsAsync<FeatureRunAlreadyStoppedException>(() => _featureRunService.StopFeatureRun(new StopFeatureRunRequest
247+
{
248+
RunId = "stopped-run-changed-settings",
249+
StopResult = "AllB"
250+
}));
251+
Assert.ThrowsAsync<FeatureRunAlreadyStoppedException>(() => _featureRunService.StopFeatureRun(new StopFeatureRunRequest
252+
{
253+
RunId = "stopped-run-all-a",
254+
StopResult = "AllB"
255+
}));
256+
Assert.ThrowsAsync<FeatureRunAlreadyStoppedException>(() => _featureRunService.StopFeatureRun(new StopFeatureRunRequest
257+
{
258+
RunId = "stopped-run-removed-from-code",
259+
StopResult = "AllB"
260+
}));
261+
}
262+
263+
[Test]
264+
public async Task StoppedAllBRunsCanBeChanged()
265+
{
266+
Assert.DoesNotThrowAsync(() => _featureRunService.StopFeatureRun(new StopFeatureRunRequest
267+
{
268+
RunId = "stopped-run-all-b",
269+
StopResult = "AllA"
270+
}));
271+
}
202272
}
203273
}

0 commit comments

Comments
 (0)