Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide API to do post-process right after a certain action executed #31

Closed
ipdae opened this issue Jan 9, 2019 · 7 comments

Comments

Projects
None yet
3 participants
@ipdae
Copy link
Member

commented Jan 9, 2019

In games that currently use libplanet, there is no way to know created action has been processed.
so, in the game, we waiting for process has finished like this.
However, this can cause the game to hang if the block containing the Tx is not included in the block chain.
In my opinion, if libplanet provides an event based on the result of the process, the game will be handling the internal state change as event-driven and solved the problem.

@ipdae ipdae changed the title (WIP)Suggestion: Invoke event when block created. Suggestion: Invoke event like Action.processed Jan 10, 2019

@dahlia dahlia changed the title Suggestion: Invoke event like Action.processed Event like Action.processed Feb 11, 2019

@moreal

This comment has been minimized.

Copy link
Contributor

commented Mar 28, 2019

the link looks like broken :(
Now, how is it working? (this issue)

@dahlia

This comment has been minimized.

Copy link
Member

commented Mar 28, 2019

Ah, that repository seems not public yet. ☹️

@dahlia

This comment has been minimized.

Copy link
Member

commented Mar 28, 2019

Quote the code he referred to:

private IEnumerator SleepAsync()
{
    var tables = this.GetRootComponent<Data.Tables>();
    Data.Table.Stats statsData;
    if (tables.Stats.TryGetValue(ActionManager.Instance.Avatar.Level, out statsData))
    {
        ActionManager.Instance.Sleep(statsData);
        while (ActionManager.Instance.Avatar.CurrentHP == ActionManager.Instance.Avatar.HPMax)
        {
            yield return new WaitForSeconds(1.0f);
        }
    }
    OnRoomEnter();
}
@dahlia

This comment has been minimized.

Copy link
Member

commented Mar 28, 2019

The quoted code looks helpful to explain his intention though.

To sum up, the current API enforces game apps to poll every state change of the blockchain in order to execute game logic depending on that that state change, which is inefficient.

@moreal

This comment has been minimized.

Copy link
Contributor

commented Mar 29, 2019

I agree about that opinion, the pattern based on event
It'll be so helpful for reducing useless waiting.

@dahlia dahlia added this to the 0.3.0 milestone Apr 8, 2019

@dahlia dahlia self-assigned this Apr 8, 2019

@dahlia

This comment has been minimized.

Copy link
Member

commented Apr 10, 2019

I started to work on this yesterday, and have sketched my rough idea on it. Let me explain my current idea.

The reason why we need to be aware when an action is actually processed (whatever it technically means) is not to create a new consequent action that depends on previous states causes by the previous action. Making an action depending on another action is already possible and easy; you only need to put both actions into two different blocks.

To me, the real reason why we need a such event handler is to render the result to display it to game players. More precisely, in order to render it as early as possible right after it gets determined. “Determined” here technically means ⅰ) a block that the action was put into is mined, ⅱ) a branch containing that block is promoted as the canon, and ⅲ) that block is finalized in the network.

Unfortunately, Libplanet's blockchain does not satisfy finality at present, and even if it already satisfies finality, the latency between the moment an action is created and the moment a block which contains that action is promoted and finalized in the network is too high for multiplayer games. So let's deal with only ⅰ) and ⅱ) at the moment.

There are two moments that a node becomes aware that a block is promoted (or, treated as a candidate at least): a) when another node propagates that block which is not mined by this node, and b) when another node propagates a next block on top of that block which is mined by this node. The reason to wait a next block in the case b) is for minimal finality. If low latency is prior to finality we might determine it early: b²) when that block which is mined by this node is propagated to other n nodes.

At such moments, Swarm could notify a signal to BlockChain<T>, and BlockChain<T> calls post-processing callbacks of all actions in the block received through that signal. These callbacks purpose to render something for the most part, so I'm considering to name it Render(). It also needs the current states of the blockchain, so Render() method should be given them:

public interface IAction
{
    // Other methods are omitted here.
    IAccountStateDelta Execute(IActionContext context);
    void Render(AccountStateGetter previousStateGetter, AccountStateGetter nextStateGetter);
}

What if a block which consists of already Render()ed actions loses its status as a canon? Since Libplanet's blockchain currently doesn't satisfy finality, such situations may occur, so we need to deal with this. My best idea to deal with this at the moment is to add another method named Unrender() which rolls back the effect made by an action:

public interface IAction
{
    // Other methods are omitted here.
    IAccountStateDelta Execute(IActionContext context);
    void Render(AccountStateGetter previousStateGetter, AccountStateGetter nextStateGetter);
    void Unrender(AccountStateGetter nextStateGetter, AccountStateGetter previousStateGetter);
}

When an existing canon branch is replaced by a new canon branch, Swarm currently calls BlockChain<T>.Swap() under the hood. Swarm determines the branch point between two branches, so it can tell BlockChain<T>.Swap() what blocks should be invalidated. When IAction.Unrender() methods are called, they should be invoked in the reverse order when the Render() methods are called.

Although I should adjust API details, could anyone leave comments on this?

@dahlia dahlia changed the title Event like Action.processed Provide API to do post-process right after a certain action executed Apr 16, 2019

@dahlia dahlia added the suggestion label Apr 16, 2019

@dahlia dahlia closed this Apr 29, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.