Skip to content

Conversation

@parfeon
Copy link
Contributor

@parfeon parfeon commented May 18, 2023

feat(ee): event engine implementation

Provide generic event engine implementation which can operate over different states.

feat(ee): provide subscribe states

Provide a list of states which correspond to subscribe state machine.

feat(ee): provide list of subscribe state machine events

Provide a list of events which trigger transition between states in subscribe state machine.

feat(ee): define transitions

Define transition directions in response to event, depending on from current state machine state.

feat(ee): provide list of effects and invocations

Provide a list of effects invocation and effects which can be called as part of transitions.

Provide generic event engine implementation which can operate over different states.

feat(ee): provide subscribe states

Provide list of states which correspond to subscribe state machine.

feat(ee): provide list of subscribe state machine events

Provide list of events which trigger transition between states in subscribe state machine.

feat(ee): define transitions

Define transition directions in response of event depending from current state machine state.

feat(ee): provide list of effects and invocations

Provide list of effects invocation and effects which can be called as part of transitions.
@parfeon parfeon self-assigned this May 18, 2023
@parfeon
Copy link
Contributor Author

parfeon commented May 18, 2023

FYI: Clippy won't be happy with this because a lot of code detached (it needs to be bound with actual effect implementation and EE usage).

@Xavrax
Copy link
Contributor

Xavrax commented May 18, 2023

You can add #[allow(dead_code)] for the whole modules.

Copy link
Contributor

@Xavrax Xavrax left a comment

Choose a reason for hiding this comment

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

Overall LGTM but I have some questions.

Comment on lines 89 to 91
let mut writable_state = self.current_state.write();
*writable_state = transition.state;
drop(writable_state);
Copy link
Contributor

Choose a reason for hiding this comment

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

This pattern is also pretty common in rust community:

Suggested change
let mut writable_state = self.current_state.write();
*writable_state = transition.state;
drop(writable_state);
{
let mut writable_state = self.current_state.write();
*writable_state = transition.state;
}

I prefer that one above but take this one which is preferred by you.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Made this change in recent push.

Copy link
Contributor

@Xavrax Xavrax left a comment

Choose a reason for hiding this comment

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

What thing makes me worried. There are 1.5k lines without any test ;o

Copy link
Contributor

@Xavrax Xavrax left a comment

Choose a reason for hiding this comment

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

Some question that I found during working with effects.

F: Fn(Vec<E>),
{
if let Some(effect) = self.handler.create(invocation) {
let effect = Rc::new(effect);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need that RC here?
Why do we passing the remove_managed_effect into the effect and call it inside of it?

Additionally, if we need reference counter it probably won't work with our client as it needs to be thread safe.
Use Arc instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why do we need that RC here?

I have a requirement to store managed effect in a vector and make it possible to remove the same effect from list after run completion.
I tried to filter in completion block, but borrow checker won't let me go this way. Furthermore, I used Rc just to make clone once to add it vector and don't need Rc functionality after that.

Why do we passing the remove_managed_effect into the effect and call it inside of it?

I can't follow this one.
The idea was that run function of effect has completion closure, with which we will be able to remove effect from the list of managed effects.

Additionally, if we need reference counter it probably won't work with our client as it needs to be thread safe.
Use Arc instead.

Rc functionality used once (I mean clone) within dispatch function, and that is all. All other access to it through vector which stores it should be safe enough because of RwLock.

Copy link
Contributor

@Xavrax Xavrax May 24, 2023

Choose a reason for hiding this comment

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

The idea was that run function of effect has completion closure, with which we will be able to remove effect from the list of managed effects.

This one is still confusing to me.
How effects are allowed to managed the call?
Currently in SubscribeEffect it doesn't make any decision about it. Do you think that some effects will affect that?
We still can casually call that line after calling run function.

@parfeon
Copy link
Contributor Author

parfeon commented May 22, 2023

What thing makes me worried. There are 1.5k lines without any test ;o

I will work on this.

F: Fn(Vec<E>),
{
if let Some(effect) = self.handler.create(invocation) {
let effect = Rc::new(effect);
Copy link
Contributor

@Xavrax Xavrax May 24, 2023

Choose a reason for hiding this comment

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

The idea was that run function of effect has completion closure, with which we will be able to remove effect from the list of managed effects.

This one is still confusing to me.
How effects are allowed to managed the call?
Currently in SubscribeEffect it doesn't make any decision about it. Do you think that some effects will affect that?
We still can casually call that line after calling run function.

Comment on lines +65 to +67
// Notify about effect run completion.
// Placeholder for effect events processing (pass to effects handler).
f(events);
Copy link
Contributor

Choose a reason for hiding this comment

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

So these lines assume's that f() have to be called after the Effect.
As it's synchronous - I still don't see sense of that call. Maybe Am I missing something ;o?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We don't have implemented effects yet, but I assume that some of them would return events, which should be processed by the event engine.
It is exactly as it says – it is a placeholder for functionality, which I expect to appear with implemented effects.
The function pointer can be passed to the created effect, so it will be called from it.

Copy link
Contributor

@Xavrax Xavrax May 24, 2023

Choose a reason for hiding this comment

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

I'm still not sure about that.
Anyway imo you can merge that.
Rest of code looks good.

Copy link
Contributor

@Xavrax Xavrax left a comment

Choose a reason for hiding this comment

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

LGTM (except that part with function)

@Xavrax Xavrax merged commit 665b518 into phoenix May 25, 2023
@Xavrax Xavrax deleted the clen-1219/feat/add-ee-transitions branch May 25, 2023 09:48
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.

2 participants