Skip to content

Async step timeouts - #1834

Open
vkalapov wants to merge 7 commits into
masterfrom
async-step-timeouts
Open

vkalapov wants to merge 7 commits into
masterfrom
async-step-timeouts

Conversation

@vkalapov

Copy link
Copy Markdown
Contributor

LMCROSSITXSADEPLOY-3322

@vkalapov
vkalapov force-pushed the async-step-timeouts branch from 51adc0c to f3efdb1 Compare May 18, 2026 09:05
@sonarqubecloud

Copy link
Copy Markdown


@Override
public Duration getTimeout(ProcessContext context) {
return calculateTimeout(context, TimeoutType.BIND_SERVICE);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why checking a service key operation is using BIND_SERVICE instead of CREATE_SERVICE_KEY


@Named("globalTimeoutSettingStep")
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class GlobalTimeoutSettingStep extends SyncFlowableStep {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use constructor injection

return timeoutType.isModuleScoped() ? moduleTimeoutSources : serviceTimeoutSources;
}

public DeploymentDescriptor getDeploymentDescriptor(ProcessContext context, StepLogger stepLogger) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why TimeoutValueResolved has a method for getting the DeploymentDescriptor from context. This breaks single responsibility principle

Comment on lines +58 to +60
if (!timeoutType.isServiceScoped()) {
return false;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this check needed for?

Comment on lines +67 to +68
String timeoutSeconds = timeout != null ? String.valueOf(timeout.toSeconds()) : "null";
getStepLogger().debug(Messages.TIMEOUT_0_EQUALS_1_SECONDS_FROM_2,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we say the parameter is not set instead of logging 'null' strings?

import org.cloudfoundry.multiapps.mta.model.Resource;

@Named
public class TimeoutServiceResourceNameResolver {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used beyond tests?

Comment on lines +28 to +29
private interface TimeoutSource {
Optional<TimeoutResolution> resolve(ProcessContext context, TimeoutType timeoutType, StepLogger logger);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why TimeoutSource has a resolve method? Rename to some resolver?

return DurationUtil.parseDuration(timeout, timeoutParameterName, maxAllowedValue);
}

private Optional<Module> findModuleByAppName(DeploymentDescriptor descriptor, String appName) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The module name and the app-name might not always match. Can we reuse some already existing method util instead of having another similar method?

public record TimeoutResolution(Duration timeout, String parameterName) {
}

private final List<TimeoutSource> moduleTimeoutSources = List.of(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the whole logic a bit over engineered with all these lambdas and records?

Comment on lines +317 to +319
.filter(type -> originalParameters.containsKey(type.getProcessVariable()
.getName()))
.forEach(type -> targetParameters.put(type.getOperationParamsFlag()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the point of setting these variables to true if they are hardcoded in the enum while their default value is false?

@vkalapov
vkalapov force-pushed the async-step-timeouts branch from f3efdb1 to 86d67e4 Compare October 13, 2026 09:04
Introduce the vocabulary for configurable service operation timeouts:
- SupportedParameters: resource-level (create-service-timeout,
  bind-service-timeout, create-service-key-timeout) and global-level
  (services-*) parameter names
- Variables: the CLI-override process variables and the bind global
  fallback
- CloudServiceInstanceExtended: resource-level timeout fields, populated
  by ServicesCloudModelBuilder from the service's mtad parameters
- DurationUtil: parse and validate raw timeout values into Duration
- Constants: fixed ceilings for delete-service, delete-service-key and
  unbind-service operations
Add the timeout resolution engine:
- TimeoutType: declares, per operation, its parameter names, CLI process
  variable, maximum value, and (for services) how to read the timeout off
  the service instance
- TimeoutValueResolver: resolves a timeout by priority — CLI process
  variable, then resource/service-object value, then global descriptor
  parameter, then the default. Bind additionally falls back to a
  pre-resolved global variable because its subprocess has no descriptor
- TimeoutStepStateManager: tracks per-step elapsed time with correct
  reset semantics across retries and poll cycles
Wire the async steps to the resolver:
- TimeoutAsyncFlowableStep: resolve and log the timeout, then enforce it
  via the step state manager on every execution
- Create/Bind/CheckServiceBinding/CheckServiceKey steps resolve their
  configurable timeout from the resolver
- Delete/DeleteServiceKey/Unbind steps adopt a fixed safety ceiling
  (previously unbounded)
- ProcessDescriptorStep pre-resolves the global bind timeout into a
  process variable for the binding subprocess, which has no descriptor
Register the create-service, bind-service and create-service-key timeout
parameters (with their integer conversion) in the deploy, blue-green, CTS
and rollback metadata so they are accepted and converted to process
variables. Update metadata tests accordingly.
@vkalapov
vkalapov force-pushed the async-step-timeouts branch 2 times, most recently from ca7e8a6 to 50270b6 Compare October 14, 2026 11:23
@vkalapov
vkalapov force-pushed the async-step-timeouts branch from 50270b6 to 7f1c661 Compare October 14, 2026 11:25
return Optional.empty();
}
long seconds = number.longValue();
return seconds > 0 ? Optional.of(Duration.ofSeconds(seconds)) : Optional.empty();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the method above we have max value, don't we need here also a max value?

Comment on lines +1006 to +1008
Variable<Duration> BIND_SERVICE_TIMEOUT_GLOBAL_FALLBACK = ImmutableSimpleVariable.<Duration> builder()
.name("servicesBindServiceTimeoutGlobalFallback")
.build();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need default value for this Variable

@sonarqubecloud

Copy link
Copy Markdown

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants