Skip to content

Conversation

@shultseva
Copy link
Contributor

@shultseva shultseva commented Dec 15, 2025

@shultseva shultseva requested a review from a team as a code owner December 15, 2025 12:20
@netlify
Copy link

netlify bot commented Dec 15, 2025

Deploy Preview for hardcore-allen-f5257d ready!

Name Link
🔨 Latest commit 97fc680
🔍 Latest deploy log https://app.netlify.com/projects/hardcore-allen-f5257d/deploys/6945820b5bef2a0008e3ade3
😎 Deploy Preview https://deploy-preview-2037--hardcore-allen-f5257d.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@Rob-Hazelcast Rob-Hazelcast self-assigned this Dec 15, 2025
Comment on lines 768 to 775
The major use case of stateful mapping is recognizing a pattern in the
event stream, such as matching start-transaction with end-transaction
events based on an event correlation ID. More generally, you can
implement any kind of state machine and detect patterns in an input of
any complexity.

As with other stateful operations, you can also use a `groupingKey` to
have a unique state per key.
Copy link
Contributor

@k-jamroz k-jamroz Dec 17, 2025

Choose a reason for hiding this comment

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

these paragraphs ("The major use case...", "As with other stateful operations...") should be first - they are high-level description

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I disagree. I think it would be better to first provide a general description of the parameter, explain the difference between keyed and non-keyed cases, and then describe the general pattern and how it can be solved using this method. Let’s leave it to @Rob-Hazelcast to decide.

Copy link
Contributor

Choose a reason for hiding this comment

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

Either works. I think the current structure is good because the high level use case description leads into the example code. The alternative would work better if it was broken up into child sections - intro, detailed description, example.

Copy link
Contributor

Choose a reason for hiding this comment

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

I prefer top-to-bottom approach in documentation (first what it is for and later how it works), but that is not a hill I am willing to die on

The state object is created using `createFn` and is passed to `mapFn` together with each input item.
The function can update the state and emit a single output item (or null if no output is needed).

For each grouping key, Jet maintains a dedicated state object created by the supplied `createFn`.
Copy link
Contributor

@k-jamroz k-jamroz Dec 17, 2025

Choose a reason for hiding this comment

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

nit: I'd consider merging some of the paragraphs - currently there are a lot of short paragraphs, which makes it harder to scan the text

Copy link
Contributor

Choose a reason for hiding this comment

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

or possibly group keyed and non-keyed descrtiption in bulletpoints or subsections

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the short paragraphs are fine. Bullets are a good idea and it might be nice to resolve the repetition ("the function can update the state and..."), but I'm not too worried about it.

NB: Sentences on adjacent lines are combined into paragraphs in the output, so they're not as short as they appear here - not sure if that was your concern or if you think they're too short in the output too.

Copy link
Contributor

Choose a reason for hiding this comment

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

"The non-keyed mapStateful" paragraph applies to non-keyed variant, the next 5 paragraphs apply ONLY to keyed variant (TTL, eviction, forced eviction) but this is not visible in the text and a bit confusing and harder to understand

Rob-Hazelcast and others added 6 commits December 17, 2025 16:53
Co-authored-by: Krzysztof Jamróz <79092062+k-jamroz@users.noreply.github.com>
Co-authored-by: Krzysztof Jamróz <79092062+k-jamroz@users.noreply.github.com>
Co-authored-by: Krzysztof Jamróz <79092062+k-jamroz@users.noreply.github.com>
Co-authored-by: Krzysztof Jamróz <79092062+k-jamroz@users.noreply.github.com>
@shultseva shultseva requested a review from k-jamroz December 18, 2025 14:36
Copy link
Contributor

@Rob-Hazelcast Rob-Hazelcast left a comment

Choose a reason for hiding this comment

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

Looks great, thanks! Good level of explanation / examples, very clear.

The state object is created using `createFn` and is passed to `mapFn` together with each input item.
The function can update the state and emit a single output item (or null if no output is needed).

For each grouping key, Jet maintains a dedicated state object created by the supplied `createFn`.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the short paragraphs are fine. Bullets are a good idea and it might be nice to resolve the repetition ("the function can update the state and..."), but I'm not too worried about it.

NB: Sentences on adjacent lines are combined into paragraphs in the output, so they're not as short as they appear here - not sure if that was your concern or if you think they're too short in the output too.

Comment on lines 768 to 775
The major use case of stateful mapping is recognizing a pattern in the
event stream, such as matching start-transaction with end-transaction
events based on an event correlation ID. More generally, you can
implement any kind of state machine and detect patterns in an input of
any complexity.

As with other stateful operations, you can also use a `groupingKey` to
have a unique state per key.
Copy link
Contributor

Choose a reason for hiding this comment

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

Either works. I think the current structure is good because the high level use case description leads into the example code. The alternative would work better if it was broken up into child sections - intro, detailed description, example.

The state object is created using `createFn` and is passed to `mapFn` together with each input item.
The `mapFn` function can update the state and emit a single output item or return null if no output is needed.

For each grouping key, Jet maintains a dedicated state object created by the supplied `createFn`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
For each grouping key, Jet maintains a dedicated state object created by the supplied `createFn`.
In the keyed `mapStateful` Jet maintains a dedicated state object created by the supplied `createFn` for each grouping key.

so it differentiates from previous paragraph

implement any kind of state machine and detect patterns in an input of
any complexity.

As with other stateful operations, you can also use a `groupingKey` to
Copy link
Contributor

Choose a reason for hiding this comment

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

"As with other stateful operations, you can also use a groupingKey to" - is this part of the use case or rather a general description of the operator? We are introducing keyed variant again, which we did technically and not very explicitly ~7 paragraphs before. In the original version it was very close to the beginning so was much more natural, now it is after a long technical description.

Comment on lines +869 to +870
() -> new TransactionEvent[2],
(state, id, event) -> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
() -> new TransactionEvent[2],
(state, id, event) -> {
() -> new TransactionEvent[2],
(state, id, event) -> {

Comment on lines +885 to +886
// End of transaction received; this state is no longer needed
return state[1] != null;
Copy link
Contributor

@k-jamroz k-jamroz Dec 19, 2025

Choose a reason for hiding this comment

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

we cannot evict after receiving only TRANSACTION_END because the events can come out of order:

Suggested change
// End of transaction received; this state is no longer needed
return state[1] != null;
// we have both start and end events
return state[0] != null && state[1] != null;

Copy link
Contributor

Choose a reason for hiding this comment

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

BTW, this seems to be a general pattern: deleteStatePredicate will often have the same condition as condition for generating final output from mapFn

},
// delete state immediately after transaction end
(state, txId, event) ->
event.getType() == EventType.TRANSACTION_END,
Copy link
Contributor

Choose a reason for hiding this comment

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

this example is less than ideal if events are allowed out of order and some may come after TRANSACTION_END

Copy link
Contributor

@k-jamroz k-jamroz left a comment

Choose a reason for hiding this comment

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

Approving in advance, the content as a whole is good. Need to fix example. As to the form - I expressed my preferences, but we can also keep it as is.

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