Skip to content

Commit 2446a97

Browse files
feat(zebra): Configure max job time limit based on a feature flag (#378)
## 📝 Description Makes max job execution time limit configurable via feature flag.
1 parent 561bcf6 commit 2446a97

File tree

4 files changed

+102
-8
lines changed

4 files changed

+102
-8
lines changed

zebra/lib/zebra/apis/internal_task_api/schedule.ex

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ defmodule Zebra.Apis.InternalTaskApi.Schedule do
7272
repository_id: req.repository_id,
7373
machine_type: job_req.agent.machine.type,
7474
machine_os_image: job_req.agent.machine.os_image,
75-
execution_time_limit: valid_time_limit(job_req.execution_time_limit),
75+
execution_time_limit:
76+
configure_execution_time_limit(req.org_id, job_req.execution_time_limit),
7677
priority: valid_priority(job_req.priority),
7778
spec:
7879
Spec.new(
@@ -126,11 +127,32 @@ defmodule Zebra.Apis.InternalTaskApi.Schedule do
126127
defp valid_priority(_), do: @default_job_priority
127128

128129
# value of execution_time_limit is received in minutes and it is stored in seconds
129-
defp valid_time_limit(value)
130-
when value > 0 and value <= @max_job_execution_time_limit,
131-
do: value * 60
130+
def configure_execution_time_limit(org_id, req_value) do
131+
{max_job_time_limit, deafult_job_time_limit} = find_max_and_default_job_time_limits(org_id)
132132

133-
defp valid_time_limit(_), do: @default_job_execution_time_limit
133+
if req_value > 0 and req_value <= max_job_time_limit do
134+
req_value * 60
135+
else
136+
deafult_job_time_limit
137+
end
138+
end
139+
140+
defp find_max_and_default_job_time_limits(org_id) do
141+
if FeatureProvider.feature_enabled?(:max_job_execution_time_limit, param: org_id) do
142+
max_limit = FeatureProvider.feature_quota(:max_job_execution_time_limit, param: org_id)
143+
144+
default_limit =
145+
if max_limit * 60 < @default_job_execution_time_limit do
146+
max_limit * 60
147+
else
148+
@default_job_execution_time_limit
149+
end
150+
151+
{max_limit, default_limit}
152+
else
153+
{@max_job_execution_time_limit, @default_job_execution_time_limit}
154+
end
155+
end
134156

135157
def encode_fail_fast_strategy(strategy) do
136158
alias InternalApi.Task.ScheduleRequest.FailFast, as: FF

zebra/test/support/stubbed_provider.ex

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,28 @@ defmodule Support.StubbedProvider do
22
use FeatureProvider.Provider
33

44
@impl FeatureProvider.Provider
5-
def provide_features(_org_id \\ nil, _opts \\ []) do
5+
def provide_features(org_id \\ nil, _opts \\ []) do
66
{:ok,
77
[
88
feature("max_paralellism_in_org", [:enabled, {:quantity, 500}]),
99
feature("cache_cli_parallel_archive_method", [:hidden]),
10-
feature("some_custom_feature", [:hidden])
10+
feature("some_custom_feature", [:hidden]),
11+
max_job_time_limit_feature(org_id)
1112
]}
1213
end
1314

15+
defp max_job_time_limit_feature("enabled_30") do
16+
feature("max_job_execution_time_limit", [:enabled, {:quantity, 30}])
17+
end
18+
19+
defp max_job_time_limit_feature("enabled_48h") do
20+
feature("max_job_execution_time_limit", [:enabled, {:quantity, 48 * 60}])
21+
end
22+
23+
defp max_job_time_limit_feature(_org_id) do
24+
feature("max_job_execution_time_limit", [:hidden])
25+
end
26+
1427
@impl FeatureProvider.Provider
1528
def provide_machines(_org_id \\ nil, _opts \\ []) do
1629
{:ok,

zebra/test/zebra/apis/internal_task_api/schedule_test.exs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ defmodule Zebra.Apis.InternalTaskApi.ScheduleTest do
33

44
alias Zebra.Apis.InternalTaskApi.Schedule
55

6+
# in seconds
7+
@default_job_execution_time_limit 24 * 60 * 60
8+
69
describe ".schedule" do
710
test "it creates task with jobs" do
811
token = Ecto.UUID.generate()
@@ -141,6 +144,62 @@ defmodule Zebra.Apis.InternalTaskApi.ScheduleTest do
141144
end
142145
end
143146

147+
describe ".configure_execution_time_limit" do
148+
test "when feature is disabled and limit from request is valid => returns limit from request in seconds" do
149+
org_id = UUID.uuid4()
150+
151+
assert 180 * 60 == Schedule.configure_execution_time_limit(org_id, 180)
152+
end
153+
154+
test "when feature is disabled and limit from request is invalid => returns default limit in seconds" do
155+
org_id = UUID.uuid4()
156+
157+
# if requested limit <= 0 -> configure it to default one
158+
assert @default_job_execution_time_limit ==
159+
Schedule.configure_execution_time_limit(org_id, 0)
160+
161+
assert @default_job_execution_time_limit ==
162+
Schedule.configure_execution_time_limit(org_id, -5)
163+
164+
# if requested limit >= max time limit -> configure it to default one
165+
assert @default_job_execution_time_limit ==
166+
Schedule.configure_execution_time_limit(org_id, 48 * 60)
167+
end
168+
169+
test "when feature is enabled and limit from request is valid => returns limit from request in seconds" do
170+
org_id = "enabled_30"
171+
172+
# requested limit is less then feature limit of 30 minutes
173+
assert 15 * 60 == Schedule.configure_execution_time_limit(org_id, 15)
174+
end
175+
176+
test "when feature is enabled, limit from request is invalid, and feature limit >= default limit => returns default limit" do
177+
org_id = "enabled_48h"
178+
179+
# if requested limit <= 0 and feature limit >= max limit -> configure it to default one
180+
assert @default_job_execution_time_limit ==
181+
Schedule.configure_execution_time_limit(org_id, 0)
182+
183+
assert @default_job_execution_time_limit ==
184+
Schedule.configure_execution_time_limit(org_id, -5)
185+
186+
# if requested limit > feature limit and feature limit >= max limit -> configure it to default one
187+
assert @default_job_execution_time_limit ==
188+
Schedule.configure_execution_time_limit(org_id, 72 * 60)
189+
end
190+
191+
test "when feature is enabled, limit from request is invalid, and feature limit < default limit => returns feature limit" do
192+
org_id = "enabled_30"
193+
194+
# if requested limit <= 0 and feature limit < max limit -> configure it to feature limit
195+
assert 30 * 60 == Schedule.configure_execution_time_limit(org_id, 0)
196+
assert 30 * 60 == Schedule.configure_execution_time_limit(org_id, -5)
197+
198+
# if requested limit > feature limit and feature limit < max limit -> configure it to feature limit
199+
assert 30 * 60 == Schedule.configure_execution_time_limit(org_id, 180)
200+
end
201+
end
202+
144203
#
145204
# Utils
146205
#

zebra/test/zebra/workers/feature_provider_invalidator_worker_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ defmodule Zebra.Workers.FeatureProviderInvalidatorWorkerTest do
9999
Worker.features_changed(callback_message)
100100

101101
{:ok, features} = FeatureProvider.list_features()
102-
assert length(features) == 3
102+
assert length(features) == 4
103103
end
104104

105105
test "when the organization feature state changes, organization feature caches are invalidated" do

0 commit comments

Comments
 (0)