fix #1252: Add predictable naming to tasks instead of UUIDs#1253
fix #1252: Add predictable naming to tasks instead of UUIDs#1253ricardozanini wants to merge 2 commits intoserverlessworkflow:mainfrom
Conversation
…of UUIDs Signed-off-by: Ricardo Zanini <ricardozanini@gmail.com>
There was a problem hiding this comment.
Pull request overview
Updates the Java fluent DSL to generate deterministic task names when callers pass null/blank names (and when using name-less overloads), replacing previously random UUID-based naming to improve debuggability and testability (Issue #1252).
Changes:
- Replace UUID defaults in fluent SPI convenience overloads with
nullso builders can apply deterministic naming. - Implement deterministic auto-naming in task list builders via a
taskType-indexscheme. - Add a new JUnit test suite covering auto-naming across top-level and nested task builders (try/forEach/fork).
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/TaskItemDefaultNamingTest.java | Adds unit tests asserting deterministic default naming for unnamed tasks (including nested builders). |
| fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/TryCatchFluent.java | Changes default overload to pass null (enabling deterministic naming downstream). |
| fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SwitchTaskFluent.java | Changes default overload to pass null for switch item names. |
| fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SwitchFluent.java | Changes default overload to pass null (enabling deterministic naming downstream). |
| fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SetFluent.java | Changes default overloads to pass null (enabling deterministic naming downstream). |
| fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/RaiseFluent.java | Changes default overload to pass null (enabling deterministic naming downstream). |
| fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ListenFluent.java | Changes default overload to pass null (enabling deterministic naming downstream). |
| fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ForkFluent.java | Changes default overload to pass null (enabling deterministic naming downstream). |
| fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ForEachFluent.java | Changes default overload to pass null (enabling deterministic naming downstream). |
| fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/EmitFluent.java | Changes default overload to pass null (enabling deterministic naming downstream). |
| fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallOpenAPIFluent.java | Changes default overload to pass null (enabling deterministic naming downstream). |
| fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallHttpFluent.java | Changes default overload to pass null (enabling deterministic naming downstream). |
| fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/TaskItemListBuilder.java | Plumbs task type into default-name helper for each task kind. |
| fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseTaskItemListBuilder.java | Introduces deterministic naming helper (taskType + "-" + list.size()) and task type constants. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/spi/CallFnFluent.java | Changes default overload to pass null (enabling deterministic naming downstream). |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncTaskItemListBuilder.java | Updates func DSL list builder to use deterministic naming helper (adds TYPE_FUNCTION). |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncSwitchTaskBuilder.java | Adds deterministic naming for onPredicate(...) when name is null/blank. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForkTaskBuilder.java | Adds deterministic naming for unnamed fork branches. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForTaskBuilder.java | Adds deterministic naming for unnamed loop tasks. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| List<TaskItem> topItems = wf.getDo(); | ||
| assertEquals(1, topItems.size()); | ||
| assertEquals("try-0", topItems.get(0).getName(), "Top level tryCatch should be tryCatch-0"); |
There was a problem hiding this comment.
The assertion message says "tryCatch-0" but the expected value is "try-0". Please align the message with the expected naming to avoid confusion when the test fails.
| assertEquals("try-0", topItems.get(0).getName(), "Top level tryCatch should be tryCatch-0"); | |
| assertEquals("try-0", topItems.get(0).getName(), "Top level tryCatch should be try-0"); |
| f -> | ||
| f.each("item") | ||
| .in("$.list") | ||
| // Assuming the DSL exposes `do_` or `tasks` for inner ForEach logic |
There was a problem hiding this comment.
This comment suggests the DSL might not support .tasks(...) inside forEach, but ForEachTaskBuilder does expose tasks(...). Consider removing or updating the comment since it can mislead readers and may become stale.
| // Assuming the DSL exposes `do_` or `tasks` for inner ForEach logic | |
| // Define tasks to be executed for each item in the forEach loop |
| if (name == null || name.isBlank()) { | ||
| name = "switch-item-" + this.switchItems.size(); | ||
| } | ||
| this.switchItems.add(new SwitchItem(name, switchCase.build())); |
There was a problem hiding this comment.
SwitchTaskFluent.on(Consumer) now passes null as the name, but this builder only applies default naming in onPredicate(...) and still adds switch items with the raw name in on(String, ...). That means .on(...) will now create SwitchItems with null/blank names. Please add the same null/blank defaulting for on(String, ...) (or override on(Consumer) in this builder) so switch items always have deterministic non-blank names.
| default SELF on(Consumer<SwitchTaskFluent.SwitchCaseBuilder> switchCaseConsumer) { | ||
| return this.on(UUID.randomUUID().toString(), switchCaseConsumer); | ||
| return this.on(null, switchCaseConsumer); | ||
| } | ||
|
|
||
| SELF on(final String name, Consumer<SwitchTaskFluent.SwitchCaseBuilder> switchCaseConsumer); |
There was a problem hiding this comment.
on(Consumer) now delegates to on(null, ...), but SwitchTaskBuilder.on(String, ...) currently stores the provided name directly in new SwitchItem(name, ...). This change can produce SwitchItem entries with null/blank names, which is a behavior change from the previous UUID default and can lead to invalid or ambiguous switch definitions. Please ensure switch-case items get a deterministic non-blank default name when none is provided (e.g., based on insertion index) or keep generating a non-null default here until implementations are updated.
| public final String TYPE_SET = "set"; | ||
| public final String TYPE_FOR = "for"; | ||
| public final String TYPE_SWITCH = "switch"; | ||
| public final String TYPE_RAISE = "raise"; | ||
| public final String TYPE_FORK = "fork"; | ||
| public final String TYPE_LISTEN = "listen"; | ||
| public final String TYPE_EMIT = "emit"; | ||
| public final String TYPE_TRY = "try"; | ||
| public final String TYPE_HTTP = "http"; | ||
| public final String TYPE_OPENAPI = "openapi"; |
There was a problem hiding this comment.
The new task type constants are declared as public final instance fields. This unnecessarily expands the public API surface and creates per-instance copies; consider making them protected static final (or private constants) since they appear to be internal implementation details used for default naming.
| public final String TYPE_SET = "set"; | |
| public final String TYPE_FOR = "for"; | |
| public final String TYPE_SWITCH = "switch"; | |
| public final String TYPE_RAISE = "raise"; | |
| public final String TYPE_FORK = "fork"; | |
| public final String TYPE_LISTEN = "listen"; | |
| public final String TYPE_EMIT = "emit"; | |
| public final String TYPE_TRY = "try"; | |
| public final String TYPE_HTTP = "http"; | |
| public final String TYPE_OPENAPI = "openapi"; | |
| protected static final String TYPE_SET = "set"; | |
| protected static final String TYPE_FOR = "for"; | |
| protected static final String TYPE_SWITCH = "switch"; | |
| protected static final String TYPE_RAISE = "raise"; | |
| protected static final String TYPE_FORK = "fork"; | |
| protected static final String TYPE_LISTEN = "listen"; | |
| protected static final String TYPE_EMIT = "emit"; | |
| protected static final String TYPE_TRY = "try"; | |
| protected static final String TYPE_HTTP = "http"; | |
| protected static final String TYPE_OPENAPI = "openapi"; |
| protected final String defaultNameAndRequireConfig( | ||
| String name, Consumer<?> cfg, String taskType) { | ||
| Objects.requireNonNull(cfg, "Configurer must not be null"); | ||
|
|
||
| if (name == null || name.isBlank()) { | ||
| name = UUID.randomUUID().toString(); | ||
| return taskType + "-" + this.list.size(); | ||
| } |
There was a problem hiding this comment.
Auto-generated names currently use this.list.size() as the suffix, which makes the first generated name end with -0. Issue #1252’s example suggests set-1 for the first unnamed task; please confirm whether the index should be 1-based and adjust the implementation/tests accordingly (e.g., size() + 1) if that’s the expected contract.
Signed-off-by: Ricardo Zanini <ricardozanini@gmail.com>
Many thanks for submitting your Pull Request ❤️!
What this PR does / why we need it:
Fixes #1252
Special notes for reviewers:
Additional information (if needed):