Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Oct 06 14:14

    dependabot[bot] on npm_and_yarn

    (compare)

  • Oct 06 14:14
    dependabot[bot] closed #47
  • Oct 06 14:14
    dependabot[bot] commented #47
  • Oct 06 14:14
    dependabot[bot] labeled #62
  • Oct 06 14:14
    dependabot[bot] opened #62
  • Oct 06 14:14

    dependabot[bot] on npm_and_yarn

    Bump url-parse from 1.4.4 to 1.… (compare)

  • Sep 29 17:45
    dependabot[bot] labeled #61
  • Sep 29 17:45
    dependabot[bot] opened #61
  • Sep 29 17:45

    dependabot[bot] on npm_and_yarn

    Bump i from 0.3.5 to 0.3.7 in /… (compare)

  • Sep 03 00:51

    dependabot[bot] on npm_and_yarn

    (compare)

  • Sep 03 00:51
    dependabot[bot] closed #36
  • Sep 03 00:51
    dependabot[bot] commented #36
  • Sep 03 00:51
    dependabot[bot] labeled #60
  • Sep 03 00:51
    dependabot[bot] opened #60
  • Sep 03 00:51

    dependabot[bot] on npm_and_yarn

    Bump immer from 2.1.5 to 9.0.6 … (compare)

  • Aug 12 04:31
    dependabot[bot] labeled #59
  • Aug 12 04:31
    dependabot[bot] opened #59
  • Aug 12 04:31

    dependabot[bot] on npm_and_yarn

    Bump path-parse from 1.0.6 to 1… (compare)

  • Aug 11 00:49
    dependabot[bot] labeled #58
  • Aug 11 00:49
    dependabot[bot] opened #58
Jean-Jacques Dubray
@jdubray
Positions are all remote (or onsite).
Edward de Jong
@CodingFiend_twitter

Sounds very interesting. I don't know anything about ML unfortunately. I thought maybe you would like an introduction to Beads, i can zip through the main design features via a screenshare if you are interested.

It is far simpler than React, and can generate Web, Desktop and Mobile apps, all from a single code base. I have a graph database inside the language, so i haven't used GraphQL. I did look at Neo4J when i was doing my project; not a big fan of Cypher, they didn't go far enough.

I have a finite state machine sub-language in Beads, it is very similar to your sam-js tool, but as it is built into the language it is probably more graceful to use. I haven't actually used it, because i haven't had a complicated enough state machine to work on in terms of my examples. Once you have multiple levels of state machines, then that kind of feature is very handy.

The syntax for regular expressions was redone, and i think its the best notation that has even been devised for that often opaque part of programming. One doesn't use them much, but they are sure hard to read in the classical Unix form.

Jean-Jacques Dubray
@jdubray
Yes I'd be very interested to have that intro, I strap for time right now to explore it on my own.
david kaye
@dfkaye_twitter
@jdubray - You may recall that about a year ago I was contorted over how to separate View concerns from the SAM state-transition logic loop. Today it finally came to me: Put the SAM methods in a Web Worker and let the View respond to 1) events and send proposals to the SAM worker, and to 2) messages from the worker to update the DOM in the main thread.
What's embarrassing here is that I forgot that I had already done something like that for a spreadsheet app in the browser using a Worker to run eval() or Function() (behind strict-dynamic content security policy - that was fun).
Anyway, what do you think?
Daniel Neveux
@dagatsoin
that is a very good exemple of the decoupling power of SAM. All the part of SAM can be distributed in any component of an infrastructure.We can even run the model in WASM, action in a server (action as a service ?)
Marcus Feitoza
@mfeitoza

@jdubray - You may recall that about a year ago I was contorted over how to separate View concerns from the SAM state-transition logic loop. Today it finally came to me: Put the SAM methods in a Web Worker and let the View respond to 1) events and send proposals to the SAM worker, and to 2) messages from the worker to update the DOM in the main thread.

That's a good solution, I think SAM pattern works well with actor model.

Jean-Jacques Dubray
@metapgmr_twitter
@dfkaye_twitter sorry, for the delay. Yes, as @dagatsoin mentioned, that's the power if SAM, the pattern can be deployed across tiers. This exactly how it should be done with a PWA.
JohnGurin
@JohnGurin

Good day, everyone. I cannot find the "old" rocket launcher example where I thought I would find an answer. Here is the question:
when a timer is counting we have to re-render the timer in a view, ​where should nap go in the example?

state.render = function(model) {
    state.representation(model)
    state.nextAction(model) ;
}

In the example above render is inside state.representation(model) and if place nap check there to, then
nap and nextAction could run "simultaneously".

Is this valid approach:

    const sr = stateRepresentation( model )
    if ( nap( sr ) ) return
    render( sr )
    nextAction( model )

So if nap is true, there is no render, if nextAction is needed, then it is done only after render

https://github.com/jdubray/sam-samples/blob/master/inferno-rocket/index.html#L251-L255

Pete Barnett
@petebarnett
Hi all - I'm wondering about a situation where multiple actors implement "Next Action Predicates" that would run given the current state... If an action starts a new cycle of the reactive loop, is it simply the case that the 2nd one can wait for that to happen until it's invoked?
Is there a scenario where that might not be suitable? like a state change consists of "a product was added to the cart", and there are 2 NAPs that want to respond to that specifically... by the time the second one is invoked again, that is no longer the latest action
it makes me think there is a class of responsive action, that needs to be queued. and when it's re-invoked, decides for itself whether it still wants to act
Pete Barnett
@petebarnett
(I guess otherwise they could be composed, but only if they knew the nature of the other, and knew they were composable, and that seems more complicated than giving them a chance to re-evaluate after being popped from the stack)
then my mention of a stack raises a new question - should it be resolved that way (depth first vs breadth first)
Pete Barnett
@petebarnett
I think I've answered my own question by rubber ducking it... If you consider the model to be closed, these actors are effectively external- in that they care to be notified about changes... But the natural reaction would be to raise a new action, and we know that actions must be queued due to the synchronised nature of the model.
So the queing becomes front-loaded, instead of implemented at the nap
Pete Barnett
@petebarnett

Revisiting the above with more clarity-

Of couse a SAM "machine" only has 1 NAP function, but my project is an "cart engine" (ecommerce) that supports modular extension. Modules have an interest in implementing their own NAPs against the cart state.
The top level NAP therefore delegates responsibility to registered modules, invoking each of their NAP implementations. In effect these modules are collaborating without knowing anything about each other, but you can't just compose their actions.

This would be no problem if they only need to respond to the current state- It is only when they start to care about the "event" that led to the state change, that things become problematic. The event can be captured by the SAM machine and rendered into the current state. e.g. "itemAdded".
Child NAPs can respond to that, but of course a new cycle begins with each action, meaning the next time round, it would not be "itemAdded" anymore, and the 2nd NAP missed its chance to act.
Rocket launcher is simple because when countdown gets to 0, you stop. It's a terminating condition. But think about counting upwards, and needing something to trigger only after, when "count > 20". You need to synthesise an event like "count exceeded 20", otherwise it'll trigger in an infinite loop.

So going back to my problem - to solve the "multiple proposed actions", actions can only be queued. But from my own reading (not sure if SAM or Lamport papers) it seems like a fundamental principle that intents are strongly associated with the state from which they are raised, to the point where it seems legitimate to require a "version/sequence number" on an intent, and to reject it if the model version has changed since then.

If I start queing actions however, I break that principle... actions become deferred to be applied against future unknown states and that doesn't feel right! But I did come up with a pattern which I think addresses the problem in my use case, and would be interested to hear thoughts.

I change the wiring so that a NAP returns model proposal(s) AND a "defferedApplication" callback.
The idea is that you can define a secondary predicate, evaluated against the new state when the action is about to be applied - to determine whether it is still valid or not. i.e. return true or false.

If the change (a.k.a. Event) that caused a NAP to propose an action was "Item added to shopping cart", the "deferredApplicatoin" callback would potentially evaluate that the product was still present in the cart.

Pete Barnett
@petebarnett
...and if the above sounds like it's bending the rules with magical machinery, I would argue that it's possible to implement as a pure SAM model, by providing an action called "setFutureActions". It accepts a list of action identifiers, and of course those can be output in state representation.
You then have one pure NAP (a single function) that happens to call out to its subscribers with the current State Representation, and collects a list of "future actions". It then looks at the current state representation for existing "futureActions", and returns a proposal equivalent to "setFutureActions" + "the action that was at the front of the queue".
In this way, you get a synchronised model with a single NAP and the queuing built into the model itself.
Pete Barnett
@petebarnett
(this is all probably equivalent to NAPs just returning callbacks which produce proposals at the time they're called)
Daniel Neveux
@dagatsoin
I ran into this problem to. I solved this by adding a new responsibility to the StateRepresentation function : define what actions could.be triggered at a specific ControlState.
It is barely equivalent of what exists on the Safe demo that JJ wrote a few years ago.
Daniel Neveux
@dagatsoin
Regarding the intent queue, you can have conflict when two actions in the queue are allowed in the same ControlState but those control states can be separated in time (e.g.: the cart can be empty, the filled, then empty...). In this case I solved the issue by tagging intent whith exact same mechanism than, one more time, the SAM Safe exemple.
Another situation is also on a project I am working on, a lag compensation engine for multiplayer game. In this case I have to deals with multiple users with different ping. And this is solved by using a Lemport Clock which fits perfectly with SAM, as the exemple above, due to the "timed" nature of the algorithm.
Daniel Neveux
@dagatsoin
(writing from my phone, sorry for typos)
Pete Barnett
@petebarnett
So in the end I implemented “multiple NAPs” as callbacks- each “module” taking part in the flow has a chance to return a callback during the nap phase instead of presenting. Callbacks are added to the stack and the loop completes when that stack is empty. Each callback may receive a different state represention but it is up to the implementation whether it wants to act.
The first callback in the stack would be executed immediately anyway. Only where more than 1 is registered would each potentially receive a new state. This again only happens when a listener cares about events rather than state
To clarify, these callbacks are not registered upfront - they are returned in each cycle, where something wants to act. They are essentially single event consumers, or promises
Pete Barnett
@petebarnett
If something is dependent on a particular control state. It can determine when the callback is invoked that the control state is or isnt present- and do nothing
So yeah, i think i realised what you were sayinhg about conflict with intent queue- which is why this is still an extension of the nap, which is simply deferred- these receive the current state when they are called and present proposals (still inside nap)
Daniel Neveux
@dagatsoin
Is there a name for a pattern that can be used and composed at all level? Business level, view level, infrastructure level, etc.
Jean-Jacques Dubray
@jdubray
@JohnGurin you are correct, thats why nextAction later became the next action predicate such that you could control the rendering of the view (or response to a client) based on the next action being triggered. Some next actions allow for rendering others don't. Its not because one action gets triggered that it would prevent rendering, it's on a case by case basis. (Sorry for the delay)
Jean-Jacques Dubray
@jdubray
@petebarnett @dagatsoin SAM is not prescriptive on what happens in nap, the are a lot if actions that can be executed in parallel (if an action's role is to present a proposal)
That's why its not a good idea to implement actions that manipulate the state like MVC, or general event handlers.
You have to distinguish of course between the case of two SAM instances interacting with eath other (not a next-action in SAM sense, its a re-action).
Jean-Jacques Dubray
@jdubray
A true next action, is rather a trans-action. An action has happened (debit account), a next action must now take place. For payments, you need both the credit action and a timer, to recredit the account on timeout (no confirmation).
The is really no logical barrier on how many next action you can initiate. By definition an action has to operate on a stale state, that's why creating proposal rather than orchestration state changes is the paradigm shift that SAM introduces.
Pete Barnett
@petebarnett
Thanks @jdubray - that is enlightening
Jean-Jacques Dubray
@jdubray
The changes are subtle when you shift from orchestrating state changes to submitting a proposal, but the code is much easier to reason about when multiple actors (actions) can be involved, because very quickly the orchestration code needs to become stateful, it's hard to perceive that transition and let alone implement it, orchestration code is inherently hard to write (say WS-BPEL if you ever took a look at it or AWS step functions). People will argue: "...but you can use function generators in javascript", sure but the state is trapped in the function generator, not really accessible to any part of the application (and then what happens in the case where the process crashes and the function generator state is lost). SAM works in all cases, re-action, trans-action, simple action, ...
Jean-Jacques Dubray
@jdubray
SAM is also inherently easy to persist (see the SAM-SAFE implementation)
david kaye
@dfkaye_twitter
@jdubray For clarification, by "function generators in javascript" do you mean generator functions that create iterable/iterator objects?
That's a problem that Redux was never able to solve, unfortunately.
Jean-Jacques Dubray
@jdubray
No, I had not. Generator functions could be used to implement SAM (as you can see, it's easy to "wait for an action"), I am not sure about the other parts of the pattern like render and nap. A generator function inherently yields to the caller and wait for another call (which work well for even handlers and request/response types of interactions). I am not sure about a "reactive loop implementation" where you pass messages along the control thread.
Jean-Jacques Dubray
@jdubray
After that the author gets into the mode "with my new hammer, everything looks like a nail", that piece of code is horrendous https://jsfiddle.net/awto/y3x6L9wu/