[ https://issues.apache.org/jira/browse/BEAM-13560?focusedWorklogId=707377&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-707377 ]
ASF GitHub Bot logged work on BEAM-13560: ----------------------------------------- Author: ASF GitHub Bot Created on: 12/Jan/22 10:03 Start Date: 12/Jan/22 10:03 Worklog Time Spent: 10m Work Description: daria-malkova commented on a change in pull request #16477: URL: https://github.com/apache/beam/pull/16477#discussion_r782907002 ########## File path: playground/backend/internal/code_processing/code_processing.go ########## @@ -210,30 +157,121 @@ func Process(ctx context.Context, cacheService cache.Cache, lc *fs_tool.LifeCycl _ = processRunSuccess(pipelineLifeCycleCtx, pipelineId, cacheService, stopReadLogsChannel, finishReadLogsChannel) } +func CompileStep(ctx context.Context, cacheService cache.Cache, lc *fs_tool.LifeCycle, pipelineId uuid.UUID, sdkEnv *environment.BeamEnvs, isUnitTest bool, pipelineLifeCycleCtx context.Context, executor executors.Executor, cancelChannel chan bool) (executors.Executor, bool) { + errorChannel, successChannel := createStatusChannels() + // This condition is used for cases when the playground doesn't compile source files. For the Python code and the Go Unit Tests + if sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_PYTHON || (sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_GO && isUnitTest) { + if err := processCompileSuccess(pipelineLifeCycleCtx, []byte(""), pipelineId, cacheService); err != nil { + return executors.Executor{}, true + } + } else { // in case of Java, Go (not unit test), Scala - need compile step + // Compile + executorBuilder := builder.SetupCompilerBuilder(lc, sdkEnv) + executor = executorBuilder.Build() + logger.Infof("%s: Compile() ...\n", pipelineId) + compileCmd := executor.Compile(pipelineLifeCycleCtx) + var compileError bytes.Buffer + var compileOutput bytes.Buffer + runCmdWithOutput(compileCmd, &compileOutput, &compileError, successChannel, errorChannel) + + // Start of the monitoring of background tasks (compile step/cancellation/timeout) + ok, err := reconcileBackgroundTask(pipelineLifeCycleCtx, ctx, pipelineId, cacheService, cancelChannel, successChannel) + if err != nil { + return executors.Executor{}, true + } + if !ok { // Compile step is finished, but code couldn't be compiled (some typos for example) + err := <-errorChannel + _ = processErrorWithSavingOutput(pipelineLifeCycleCtx, err, compileError.Bytes(), pipelineId, cache.CompileOutput, cacheService, "Compile", pb.Status_STATUS_COMPILE_ERROR) + return executors.Executor{}, true + } // Compile step is finished and code is compiled + if err := processCompileSuccess(pipelineLifeCycleCtx, compileOutput.Bytes(), pipelineId, cacheService); err != nil { + return executors.Executor{}, true + } + } + return executor, false +} + +func PrepareStep(ctx context.Context, cacheService cache.Cache, lc *fs_tool.LifeCycle, pipelineId uuid.UUID, sdkEnv *environment.BeamEnvs, pipelineLifeCycleCtx context.Context, validationResults *sync.Map, cancelChannel chan bool) (executors.Executor, bool) { + errorChannel, successChannel := createStatusChannels() + executorBuilder, err := builder.SetupPreparatorBuilder(lc, sdkEnv) + if err != nil { + _ = processSetupError(err, pipelineId, cacheService, pipelineLifeCycleCtx) + return executors.Executor{}, false Review comment: Didn't notice, you are right, fixed. ########## File path: playground/backend/internal/code_processing/code_processing.go ########## @@ -210,30 +157,121 @@ func Process(ctx context.Context, cacheService cache.Cache, lc *fs_tool.LifeCycl _ = processRunSuccess(pipelineLifeCycleCtx, pipelineId, cacheService, stopReadLogsChannel, finishReadLogsChannel) } +func CompileStep(ctx context.Context, cacheService cache.Cache, lc *fs_tool.LifeCycle, pipelineId uuid.UUID, sdkEnv *environment.BeamEnvs, isUnitTest bool, pipelineLifeCycleCtx context.Context, executor executors.Executor, cancelChannel chan bool) (executors.Executor, bool) { + errorChannel, successChannel := createStatusChannels() + // This condition is used for cases when the playground doesn't compile source files. For the Python code and the Go Unit Tests + if sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_PYTHON || (sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_GO && isUnitTest) { + if err := processCompileSuccess(pipelineLifeCycleCtx, []byte(""), pipelineId, cacheService); err != nil { + return executors.Executor{}, true + } + } else { // in case of Java, Go (not unit test), Scala - need compile step + // Compile + executorBuilder := builder.SetupCompilerBuilder(lc, sdkEnv) + executor = executorBuilder.Build() + logger.Infof("%s: Compile() ...\n", pipelineId) + compileCmd := executor.Compile(pipelineLifeCycleCtx) + var compileError bytes.Buffer + var compileOutput bytes.Buffer + runCmdWithOutput(compileCmd, &compileOutput, &compileError, successChannel, errorChannel) + + // Start of the monitoring of background tasks (compile step/cancellation/timeout) + ok, err := reconcileBackgroundTask(pipelineLifeCycleCtx, ctx, pipelineId, cacheService, cancelChannel, successChannel) + if err != nil { + return executors.Executor{}, true Review comment: Make sense. Done. ########## File path: playground/backend/internal/fs_tool/java_fs.go ########## @@ -36,8 +36,7 @@ func newJavaLifeCycle(pipelineId uuid.UUID, pipelinesFolder string) *LifeCycle { } // executableName returns name that should be executed (HelloWorld for HelloWorld.class for java SDK) -func executableName(pipelineId uuid.UUID, pipelinesFolder string) (string, error) { - baseFileFolder := filepath.Join(pipelinesFolder, pipelineId.String()) +func executableName(baseFileFolder string) (string, error) { binFileFolder := filepath.Join(baseFileFolder, compiledFolderName) dirEntries, err := os.ReadDir(binFileFolder) Review comment: Good suggestion, let's fix it later when DTO will be merged ########## File path: playground/backend/internal/code_processing/code_processing.go ########## @@ -61,117 +60,65 @@ func Process(ctx context.Context, cacheService cache.Cache, lc *fs_tool.LifeCycl DeleteFolders(pipelineId, lc) }(lc) - errorChannel := make(chan error, 1) - successChannel := make(chan bool, 1) cancelChannel := make(chan bool, 1) - stopReadLogsChannel := make(chan bool, 1) - finishReadLogsChannel := make(chan bool, 1) + var validationResults sync.Map go cancelCheck(pipelineLifeCycleCtx, pipelineId, cancelChannel, cacheService) - executorBuilder, err := builder.SetupExecutorBuilder(lc, utils.ReduceWhiteSpacesToSinge(pipelineOptions), sdkEnv) - if err != nil { - _ = processSetupError(err, pipelineId, cacheService, pipelineLifeCycleCtx) + executor, done := ValidateStep(ctx, cacheService, lc, pipelineId, sdkEnv, pipelineLifeCycleCtx, &validationResults, cancelChannel) + if done { return } - executor := executorBuilder.Build() - // Validate - logger.Infof("%s: Validate() ...\n", pipelineId) - validateFunc := executor.Validate() - // Run validate function - go validateFunc(successChannel, errorChannel, &validationResults) - // Start of the monitoring of background tasks (validate function/cancellation/timeout) - ok, err := reconcileBackgroundTask(pipelineLifeCycleCtx, ctx, pipelineId, cacheService, cancelChannel, successChannel) - if err != nil { - return - } - if !ok { - // Validate step is finished, but code isn't valid - err := <-errorChannel - _ = processErrorWithSavingOutput(pipelineLifeCycleCtx, err, []byte(err.Error()), pipelineId, cache.ValidationOutput, cacheService, "Validate", pb.Status_STATUS_VALIDATION_ERROR) - return - } - // Validate step is finished and code is valid - if err := processSuccess(pipelineLifeCycleCtx, pipelineId, cacheService, "Validate", pb.Status_STATUS_PREPARING); err != nil { + executor, done = PrepareStep(ctx, cacheService, lc, pipelineId, sdkEnv, pipelineLifeCycleCtx, &validationResults, cancelChannel) + if done { return } - // Prepare - logger.Infof("%s: Prepare() ...\n", pipelineId) - prepareFunc := executor.Prepare() - // Run prepare function - go prepareFunc(successChannel, errorChannel, &validationResults) + // Check if is unit test + validateIsUnitTest, _ := validationResults.Load(validators.UnitTestValidatorName) + isUnitTest := validateIsUnitTest.(bool) - // Start of the monitoring of background tasks (prepare function/cancellation/timeout) - ok, err = reconcileBackgroundTask(pipelineLifeCycleCtx, ctx, pipelineId, cacheService, cancelChannel, successChannel) - if err != nil { - return - } - if !ok { - // Prepare step is finished, but code couldn't be prepared (some error during prepare step) - err := <-errorChannel - _ = processErrorWithSavingOutput(pipelineLifeCycleCtx, err, []byte(err.Error()), pipelineId, cache.PreparationOutput, cacheService, "Prepare", pb.Status_STATUS_PREPARATION_ERROR) - return - } - // Prepare step is finished and code is prepared - if err := processSuccess(pipelineLifeCycleCtx, pipelineId, cacheService, "Prepare", pb.Status_STATUS_COMPILING); err != nil { + executor, done = CompileStep(ctx, cacheService, lc, pipelineId, sdkEnv, isUnitTest, pipelineLifeCycleCtx, executor, cancelChannel) + if done { return } - // Check if unit test - validateIsUnitTest, _ := validationResults.Load(validators.UnitTestValidatorName) - isUnitTest := validateIsUnitTest.(bool) + // Run/RunTest + RunStep(ctx, cacheService, lc, pipelineId, isUnitTest, sdkEnv, pipelineOptions, pipelineLifeCycleCtx, cancelChannel) +} - // This condition is used for cases when the playground doesn't compile source files. For the Python code and the Go Unit Tests - if sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_PYTHON || (sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_GO && isUnitTest) { - if err := processCompileSuccess(pipelineLifeCycleCtx, []byte(""), pipelineId, cacheService); err != nil { - return - } - } else { // in case of Java, Go (not unit test), Scala - need compile step - // Compile - if sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_JAVA { - executor = executorBuilder.WithCompiler(). - WithFileName(builder.GetFileNameFromFolder(lc.GetAbsoluteSourceFolderPath())).Build() // Need changed name for unit tests - } - logger.Infof("%s: Compile() ...\n", pipelineId) - compileCmd := executor.Compile(pipelineLifeCycleCtx) - var compileError bytes.Buffer - var compileOutput bytes.Buffer - runCmdWithOutput(compileCmd, &compileOutput, &compileError, successChannel, errorChannel) +func RunStep(ctx context.Context, cacheService cache.Cache, lc *fs_tool.LifeCycle, pipelineId uuid.UUID, isUnitTest bool, sdkEnv *environment.BeamEnvs, pipelineOptions string, pipelineLifeCycleCtx context.Context, cancelChannel chan bool) { + errorChannel, successChannel := createStatusChannels() + stopReadLogsChannel := make(chan bool, 1) + finishReadLogsChannel := make(chan bool, 1) - // Start of the monitoring of background tasks (compile step/cancellation/timeout) - ok, err = reconcileBackgroundTask(pipelineLifeCycleCtx, ctx, pipelineId, cacheService, cancelChannel, successChannel) - if err != nil { - return - } - if !ok { // Compile step is finished, but code couldn't be compiled (some typos for example) - err := <-errorChannel - _ = processErrorWithSavingOutput(pipelineLifeCycleCtx, err, compileError.Bytes(), pipelineId, cache.CompileOutput, cacheService, "Compile", pb.Status_STATUS_COMPILE_ERROR) - return - } // Compile step is finished and code is compiled - if err := processCompileSuccess(pipelineLifeCycleCtx, compileOutput.Bytes(), pipelineId, cacheService); err != nil { - return - } + executorBuilder := executors.NewExecutorBuilder() + err := error(nil) + if isUnitTest { + executorBuilder, err = builder.SetupTestBuilder(lc, sdkEnv) + } else { + executorBuilder, err = builder.SetupRunBuilder(lc, utils.ReduceWhiteSpacesToSinge(pipelineOptions), sdkEnv) } - - // Run - if sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_JAVA { - executor, err = setJavaExecutableFile(lc, pipelineId, cacheService, pipelineLifeCycleCtx, executorBuilder, filepath.Join(appEnv.WorkingDir(), appEnv.PipelinesFolder())) - if err != nil { - return - } + if err != nil { + _ = processSetupError(err, pipelineId, cacheService, pipelineLifeCycleCtx) + return } - logger.Infof("%s: Run() ...\n", pipelineId) - runCmd := getExecuteCmd(&validationResults, &executor, pipelineLifeCycleCtx) + + executor := executorBuilder.Build() + logger.Infof("%s: Run()/Test() ...\n", pipelineId) + runCmd := getExecuteCmd(isUnitTest, &executor, pipelineLifeCycleCtx) var runError bytes.Buffer runOutput := streaming.RunOutputWriter{Ctx: pipelineLifeCycleCtx, CacheService: cacheService, PipelineId: pipelineId} go readLogFile(pipelineLifeCycleCtx, ctx, cacheService, lc.GetAbsoluteLogFilePath(), pipelineId, stopReadLogsChannel, finishReadLogsChannel) if sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_GO { // For go SDK all logs are placed to stdErr. file, err := os.Create(lc.GetAbsoluteLogFilePath()) + if err == nil { + runCmdWithOutput(runCmd, &runOutput, file, successChannel, errorChannel) + } Review comment: Done ########## File path: playground/backend/internal/code_processing/code_processing.go ########## @@ -210,30 +157,121 @@ func Process(ctx context.Context, cacheService cache.Cache, lc *fs_tool.LifeCycl _ = processRunSuccess(pipelineLifeCycleCtx, pipelineId, cacheService, stopReadLogsChannel, finishReadLogsChannel) } +func CompileStep(ctx context.Context, cacheService cache.Cache, lc *fs_tool.LifeCycle, pipelineId uuid.UUID, sdkEnv *environment.BeamEnvs, isUnitTest bool, pipelineLifeCycleCtx context.Context, executor executors.Executor, cancelChannel chan bool) (executors.Executor, bool) { + errorChannel, successChannel := createStatusChannels() + // This condition is used for cases when the playground doesn't compile source files. For the Python code and the Go Unit Tests + if sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_PYTHON || (sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_GO && isUnitTest) { + if err := processCompileSuccess(pipelineLifeCycleCtx, []byte(""), pipelineId, cacheService); err != nil { + return executors.Executor{}, true + } + } else { // in case of Java, Go (not unit test), Scala - need compile step + // Compile + executorBuilder := builder.SetupCompilerBuilder(lc, sdkEnv) + executor = executorBuilder.Build() + logger.Infof("%s: Compile() ...\n", pipelineId) + compileCmd := executor.Compile(pipelineLifeCycleCtx) + var compileError bytes.Buffer + var compileOutput bytes.Buffer + runCmdWithOutput(compileCmd, &compileOutput, &compileError, successChannel, errorChannel) + + // Start of the monitoring of background tasks (compile step/cancellation/timeout) + ok, err := reconcileBackgroundTask(pipelineLifeCycleCtx, ctx, pipelineId, cacheService, cancelChannel, successChannel) + if err != nil { + return executors.Executor{}, true + } + if !ok { // Compile step is finished, but code couldn't be compiled (some typos for example) + err := <-errorChannel + _ = processErrorWithSavingOutput(pipelineLifeCycleCtx, err, compileError.Bytes(), pipelineId, cache.CompileOutput, cacheService, "Compile", pb.Status_STATUS_COMPILE_ERROR) + return executors.Executor{}, true + } // Compile step is finished and code is compiled + if err := processCompileSuccess(pipelineLifeCycleCtx, compileOutput.Bytes(), pipelineId, cacheService); err != nil { + return executors.Executor{}, true + } + } + return executor, false +} + +func PrepareStep(ctx context.Context, cacheService cache.Cache, lc *fs_tool.LifeCycle, pipelineId uuid.UUID, sdkEnv *environment.BeamEnvs, pipelineLifeCycleCtx context.Context, validationResults *sync.Map, cancelChannel chan bool) (executors.Executor, bool) { + errorChannel, successChannel := createStatusChannels() + executorBuilder, err := builder.SetupPreparatorBuilder(lc, sdkEnv) + if err != nil { + _ = processSetupError(err, pipelineId, cacheService, pipelineLifeCycleCtx) + return executors.Executor{}, false + } + executor := executorBuilder.Build() + // Prepare + logger.Infof("%s: Prepare() ...\n", pipelineId) + prepareFunc := executor.Prepare() + // Run prepare function + go prepareFunc(successChannel, errorChannel, validationResults) + + // Start of the monitoring of background tasks (prepare function/cancellation/timeout) + ok, err := reconcileBackgroundTask(pipelineLifeCycleCtx, ctx, pipelineId, cacheService, cancelChannel, successChannel) + if err != nil { + return executors.Executor{}, true + } + if !ok { + err := <-errorChannel + // Prepare step is finished, but code couldn't be prepared (some error during prepare step) + _ = processErrorWithSavingOutput(pipelineLifeCycleCtx, err, []byte(err.Error()), pipelineId, cache.PreparationOutput, cacheService, "Prepare", pb.Status_STATUS_PREPARATION_ERROR) + return executors.Executor{}, true + } + // Prepare step is finished and code is prepared + if err := processSuccess(pipelineLifeCycleCtx, pipelineId, cacheService, "Prepare", pb.Status_STATUS_COMPILING); err != nil { + return executors.Executor{}, true + } + return executor, false +} + +func ValidateStep(ctx context.Context, cacheService cache.Cache, lc *fs_tool.LifeCycle, pipelineId uuid.UUID, sdkEnv *environment.BeamEnvs, pipelineLifeCycleCtx context.Context, validationResults *sync.Map, cancelChannel chan bool) (executors.Executor, bool) { + errorChannel, successChannel := createStatusChannels() + executorBuilder, err := builder.SetupValidatorBuilder(lc, sdkEnv) + if err != nil { + _ = processSetupError(err, pipelineId, cacheService, pipelineLifeCycleCtx) + return executors.Executor{}, false Review comment: Done ########## File path: playground/backend/internal/code_processing/code_processing.go ########## @@ -61,117 +60,65 @@ func Process(ctx context.Context, cacheService cache.Cache, lc *fs_tool.LifeCycl DeleteFolders(pipelineId, lc) }(lc) - errorChannel := make(chan error, 1) - successChannel := make(chan bool, 1) cancelChannel := make(chan bool, 1) - stopReadLogsChannel := make(chan bool, 1) - finishReadLogsChannel := make(chan bool, 1) + var validationResults sync.Map go cancelCheck(pipelineLifeCycleCtx, pipelineId, cancelChannel, cacheService) - executorBuilder, err := builder.SetupExecutorBuilder(lc, utils.ReduceWhiteSpacesToSinge(pipelineOptions), sdkEnv) - if err != nil { - _ = processSetupError(err, pipelineId, cacheService, pipelineLifeCycleCtx) + executor, done := ValidateStep(ctx, cacheService, lc, pipelineId, sdkEnv, pipelineLifeCycleCtx, &validationResults, cancelChannel) + if done { return } - executor := executorBuilder.Build() - // Validate - logger.Infof("%s: Validate() ...\n", pipelineId) - validateFunc := executor.Validate() - // Run validate function - go validateFunc(successChannel, errorChannel, &validationResults) - // Start of the monitoring of background tasks (validate function/cancellation/timeout) - ok, err := reconcileBackgroundTask(pipelineLifeCycleCtx, ctx, pipelineId, cacheService, cancelChannel, successChannel) - if err != nil { - return - } - if !ok { - // Validate step is finished, but code isn't valid - err := <-errorChannel - _ = processErrorWithSavingOutput(pipelineLifeCycleCtx, err, []byte(err.Error()), pipelineId, cache.ValidationOutput, cacheService, "Validate", pb.Status_STATUS_VALIDATION_ERROR) - return - } - // Validate step is finished and code is valid - if err := processSuccess(pipelineLifeCycleCtx, pipelineId, cacheService, "Validate", pb.Status_STATUS_PREPARING); err != nil { + executor, done = PrepareStep(ctx, cacheService, lc, pipelineId, sdkEnv, pipelineLifeCycleCtx, &validationResults, cancelChannel) + if done { return } - // Prepare - logger.Infof("%s: Prepare() ...\n", pipelineId) - prepareFunc := executor.Prepare() - // Run prepare function - go prepareFunc(successChannel, errorChannel, &validationResults) + // Check if is unit test + validateIsUnitTest, _ := validationResults.Load(validators.UnitTestValidatorName) + isUnitTest := validateIsUnitTest.(bool) - // Start of the monitoring of background tasks (prepare function/cancellation/timeout) - ok, err = reconcileBackgroundTask(pipelineLifeCycleCtx, ctx, pipelineId, cacheService, cancelChannel, successChannel) - if err != nil { - return - } - if !ok { - // Prepare step is finished, but code couldn't be prepared (some error during prepare step) - err := <-errorChannel - _ = processErrorWithSavingOutput(pipelineLifeCycleCtx, err, []byte(err.Error()), pipelineId, cache.PreparationOutput, cacheService, "Prepare", pb.Status_STATUS_PREPARATION_ERROR) - return - } - // Prepare step is finished and code is prepared - if err := processSuccess(pipelineLifeCycleCtx, pipelineId, cacheService, "Prepare", pb.Status_STATUS_COMPILING); err != nil { + executor, done = CompileStep(ctx, cacheService, lc, pipelineId, sdkEnv, isUnitTest, pipelineLifeCycleCtx, executor, cancelChannel) + if done { return } - // Check if unit test - validateIsUnitTest, _ := validationResults.Load(validators.UnitTestValidatorName) - isUnitTest := validateIsUnitTest.(bool) + // Run/RunTest + RunStep(ctx, cacheService, lc, pipelineId, isUnitTest, sdkEnv, pipelineOptions, pipelineLifeCycleCtx, cancelChannel) +} - // This condition is used for cases when the playground doesn't compile source files. For the Python code and the Go Unit Tests - if sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_PYTHON || (sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_GO && isUnitTest) { - if err := processCompileSuccess(pipelineLifeCycleCtx, []byte(""), pipelineId, cacheService); err != nil { - return - } - } else { // in case of Java, Go (not unit test), Scala - need compile step - // Compile - if sdkEnv.ApacheBeamSdk == pb.Sdk_SDK_JAVA { - executor = executorBuilder.WithCompiler(). - WithFileName(builder.GetFileNameFromFolder(lc.GetAbsoluteSourceFolderPath())).Build() // Need changed name for unit tests - } - logger.Infof("%s: Compile() ...\n", pipelineId) - compileCmd := executor.Compile(pipelineLifeCycleCtx) - var compileError bytes.Buffer - var compileOutput bytes.Buffer - runCmdWithOutput(compileCmd, &compileOutput, &compileError, successChannel, errorChannel) +func RunStep(ctx context.Context, cacheService cache.Cache, lc *fs_tool.LifeCycle, pipelineId uuid.UUID, isUnitTest bool, sdkEnv *environment.BeamEnvs, pipelineOptions string, pipelineLifeCycleCtx context.Context, cancelChannel chan bool) { Review comment: Done -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: github-unsubscr...@beam.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org Issue Time Tracking ------------------- Worklog Id: (was: 707377) Time Spent: 0.5h (was: 20m) > [Playground] Split builder (refactoring) > ---------------------------------------- > > Key: BEAM-13560 > URL: https://issues.apache.org/jira/browse/BEAM-13560 > Project: Beam > Issue Type: Improvement > Components: beam-playground > Reporter: Daria Malkova > Assignee: Daria Malkova > Priority: P3 > Labels: beam-playground-backend, beam-playground-sprint-7 > Time Spent: 0.5h > Remaining Estimate: 0h > > Improve usage of executor builder by splitting it to parts. > Now executor builder is created at once for all steps: validation, > preparation, compiling, and run/test. To make a change at some step we have > to change the created executor. To avoid it, we can create a builder for each > step separately after the previous steps are executed. -- This message was sent by Atlassian Jira (v8.20.1#820001)