Skip to content

Commit cb8e3ca

Browse files
committed
feat(runs): apply settings to the run spec at run creation
Signed-off-by: davidlin20dev <davidlin20.dev@gmail.com>
1 parent 8ac22b2 commit cb8e3ca

5 files changed

Lines changed: 55 additions & 4 deletions

File tree

runs/service/run_service.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414

1515
"connectrpc.com/connect"
1616
semver "github.com/Masterminds/semver/v3"
17+
"github.com/flyteorg/flyte/v2/gen/go/flyteidl2/settings"
1718
"golang.org/x/sync/errgroup"
1819
"google.golang.org/protobuf/proto"
1920
"google.golang.org/protobuf/types/known/timestamppb"
@@ -40,6 +41,7 @@ import (
4041
// RunService implements the RunServiceHandler interface
4142
type RunService struct {
4243
repo interfaces.Repository
44+
settingsRepo interfaces.SettingsRepo
4345
actionsClient actionsconnect.ActionsServiceClient
4446
projectClient projectconnect.ProjectServiceClient
4547
storagePrefix string
@@ -143,6 +145,7 @@ func (s *RunService) WatchGroups(ctx context.Context, req *connect.Request[workf
143145
// NewRunService creates a new RunService instance
144146
func NewRunService(
145147
repo interfaces.Repository,
148+
settingsRepo interfaces.SettingsRepo,
146149
actionsClient actionsconnect.ActionsServiceClient,
147150
projectClient projectconnect.ProjectServiceClient,
148151
storagePrefix string,
@@ -154,6 +157,7 @@ func NewRunService(
154157
) *RunService {
155158
return &RunService{
156159
repo: repo,
160+
settingsRepo: settingsRepo,
157161
actionsClient: actionsClient,
158162
projectClient: projectClient,
159163
storagePrefix: storagePrefix,
@@ -276,6 +280,19 @@ func (s *RunService) CreateRun(
276280
}
277281
request.RunSpec = runSpec
278282

283+
// Settings sit between an explicit request value and the static config defaults
284+
// applied below. Org is empty when the caller passed a ProjectId rather than a
285+
// RunId; the storage key encoder normalizes that to the default org.
286+
resolved, err := resolveSettings(ctx, s.settingsRepo, &settings.SettingsKey{
287+
Org: runId.GetOrg(),
288+
Domain: runId.GetDomain(),
289+
Project: runId.GetProject(),
290+
})
291+
if err != nil {
292+
return nil, connect.NewError(connect.CodeInternal, err)
293+
}
294+
applyRunSettings(runSpec, resolved)
295+
279296
// Stamp the run start time, but only for SDKs that understand it (>= 2.3.6) — older task
280297
// templates have no {{.runStartTime}} placeholder, so leaving it unset keeps the executor from
281298
// substituting anything. The scheduler sets CreateRunRequest.run_start_time to a trigger's

runs/service/settings_apply.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package service
2+
3+
import (
4+
"github.com/flyteorg/flyte/v2/gen/go/flyteidl2/settings"
5+
"github.com/flyteorg/flyte/v2/gen/go/flyteidl2/task"
6+
)
7+
8+
// applyRunSettings fills fields the caller left unset with values resolved from
9+
// settings. An explicit value in the request always wins, so this only ever fills
10+
// gaps, and a setting that is INHERIT or UNSET contributes nothing.
11+
func applyRunSettings(spec *task.RunSpec, resolved *settings.Settings) {
12+
if spec == nil {
13+
return
14+
}
15+
16+
if spec.GetQueue() == "" && resolved.GetRun().GetDefaultQueue().GetState() ==
17+
settings.SettingState_SETTING_STATE_VALUE {
18+
spec.Queue = resolved.GetRun().GetDefaultQueue().GetStringValue()
19+
}
20+
21+
// The proto defines 0 as unset for this field, so there is no explicit request for
22+
// "unlimited" to override. The settings validator bounds the value to 0 or
23+
// [2, MaxUint32], so narrowing to uint32 cannot overflow.
24+
if concurrency := resolved.GetRun().GetMaxActionConcurrency(); spec.GetMaxActionConcurrency() == 0 &&
25+
concurrency.GetState() == settings.SettingState_SETTING_STATE_VALUE {
26+
spec.MaxActionConcurrency = uint32(concurrency.GetIntValue())
27+
}
28+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package service

runs/setup.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ func Setup(ctx context.Context, sc *app.SetupContext) error {
9797
return fmt.Errorf("runs: failed to create repository: %w", err)
9898
}
9999

100+
settingsRepo := impl.NewSettingsRepo(sc.DB)
101+
100102
// In unified mode, intra-service calls go through the same mux.
101103
actionsServiceCfg := cfg.ActionsService
102104
if sc.BaseURL != "" {
@@ -129,7 +131,7 @@ func Setup(ctx context.Context, sc *app.SetupContext) error {
129131
return abortReconciler.Run(ctx)
130132
})
131133

132-
runsSvc := service.NewRunService(repo, actionsClient, projectClient, cfg.StoragePrefix, sc.DataStore, abortReconciler, cfg.AuthMetadata.ExternalAuthServerBaseURL, cfg.TrustForwardedIdentityHeaders, cfg.IdentityHeaders)
134+
runsSvc := service.NewRunService(repo, settingsRepo, actionsClient, projectClient, cfg.StoragePrefix, sc.DataStore, abortReconciler, cfg.AuthMetadata.ExternalAuthServerBaseURL, cfg.TrustForwardedIdentityHeaders, cfg.IdentityHeaders)
133135
taskSvc := service.NewTaskService(repo, projectClient)
134136

135137
runsPath, runsHandler := workflowconnect.NewRunServiceHandler(runsSvc, connect.WithInterceptors(interceptors...))
@@ -178,7 +180,7 @@ func Setup(ctx context.Context, sc *app.SetupContext) error {
178180
sc.Mux.Handle(projectPath, projectHandler)
179181
logger.Infof(ctx, "Mounted ProjectService at %s", projectPath)
180182

181-
settingsSvc := service.NewSettingsService(impl.NewSettingsRepo(sc.DB))
183+
settingsSvc := service.NewSettingsService(settingsRepo)
182184
settingsPath, settingsHandler := settingsconnect.NewSettingsServiceHandler(settingsSvc, connect.WithInterceptors(otelInterceptor))
183185
sc.Mux.Handle(settingsPath, settingsHandler)
184186
logger.Infof(ctx, "Mounted SettingsService at %s", settingsPath)

runs/test/api/setup_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ func TestMain(m *testing.M) {
114114
exitCode = 1
115115
return
116116
}
117+
118+
settingsRepo := impl.NewSettingsRepo(testDB)
119+
117120
// Services validate project existence through the ProjectService client, so mount a
118121
// real ProjectService on the same mux (mirrors production unified mode in setup.go).
119122
endpointURL := fmt.Sprintf("http://localhost:%d", testPort)
@@ -123,7 +126,7 @@ func TestMain(m *testing.M) {
123126

124127
// Create RunService with a no-op actions client (points at test server; not used by watch tests)
125128
actionsClient := actionsconnect.NewActionsServiceClient(http.DefaultClient, endpointURL)
126-
runSvc := service.NewRunService(repo, actionsClient, projectClient, "", nil, nil, "", true, config.GetConfig().IdentityHeaders)
129+
runSvc := service.NewRunService(repo, settingsRepo, actionsClient, projectClient, "", nil, nil, "", true, config.GetConfig().IdentityHeaders)
127130

128131
// Setup HTTP server
129132
mux := http.NewServeMux()
@@ -139,7 +142,7 @@ func TestMain(m *testing.M) {
139142
internalRunPath, internalRunHandler := workflowconnect.NewInternalRunServiceHandler(runSvc)
140143
mux.Handle(internalRunPath, internalRunHandler)
141144

142-
settingsSvc := service.NewSettingsService(impl.NewSettingsRepo(testDB))
145+
settingsSvc := service.NewSettingsService(settingsRepo)
143146
settingsPath, settingsHandler := settingsconnect.NewSettingsServiceHandler(settingsSvc)
144147
mux.Handle(settingsPath, settingsHandler)
145148

0 commit comments

Comments
 (0)