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

Unify all state change events on BlockChain<T> into IRenderer<T> #963

Merged
merged 11 commits into from
Aug 24, 2020

Conversation

dahlia
Copy link
Contributor

@dahlia dahlia commented Aug 21, 2020

Closes #959.

This pull request introduces a new interface named IRenderer<T> and replaces rendering methods of IAction and TipChanged/Reorged events on BlockChain<T> with it.

To make IAction to satisfy separation of concerns, the interface becomes no more aware of rendering, but only has Execute() and knows how to serialize and deserialize itself. Instead, rendering mechanism is extracted into the new interface named IRenderer<T>, and it needs to be injected into BlockChain<T>. In order to watch state changes via IRenderer<T>, BlockChain<T>() constructor now takes renderers, IEnumerable<IRenderer<T>>:

public class SampleRenderer : IRenderer<SampleAction>
{
        public void RenderAction(
            IAction action,
            IActionContext context,
            IAccountStateDelta nextStates
        ) =>
            RENDER_THINGS_HERE;
        // …
}
IRenderer<SampleAction> renderer = new SampleRenderer();
var chain = new BlockChain<SampleAction>(..., renderers: new[] { renderer });

Besides rendering IActions, IRenderer<T> also replaces BlockChain<T>.TipChanged event (introduced in #517 & #526) with IRenderer<T>.RenderBlock() method, and BlockChain<T>.Reorged event (introduced in #945) with IRenderer<T>.RenderReorg() method. It means now all events regarding state changes on BlockChain<T> become unified into one interface IRenderer<T>.

(FYI I actually left BlockChain<T>.TipChanged event private for an internal use: cancelling undergoing mining when a new block is appended. However, still it is invisible from public surface.)

This patch also removed the render option from the BlockChain<T>() constructor (introduced in #883). As renderers: null is equivalent to render: false, it's redundant.

For the sake of convenient development (writing unit tests in particular), I added two built-in renderers as well:

  • AnonymousRenderer<T> mimics Java's anonymous class for implementing IRenderer<T>. If you need only one-use renderer, it helps you to avoid a tedious inner class:

    var renderer = new AnonymousRenderer<SampleAction>
    {
        RenderAction = (action, context, nextStates) => RENDER_THINGS_HERE,
    };
  • LoggedRenderer<T> decorates another IRenderer<T> with fine-grained logging. Its constructor takes a IRenderer<T> and a Serilog ILogger, and logs starting and ending point of every event. If any exception happens during event handling it also logs the exception with traceback.

    IRenderer<SampleAction> renderer;
    renderer = new AnonymousRenderer<SampleAction> { /* … */ };
    renderer = new LoggedRenderer(renderer, Log.Logger);

@dahlia dahlia self-assigned this Aug 21, 2020
@codecov
Copy link

codecov bot commented Aug 21, 2020

Codecov Report

Merging #963 into main will increase coverage by 0.47%.
The diff coverage is 96.55%.

@@            Coverage Diff             @@
##             main     #963      +/-   ##
==========================================
+ Coverage   88.29%   88.76%   +0.47%     
==========================================
  Files         284      288       +4     
  Lines       26161    26766     +605     
==========================================
+ Hits        23099    23760     +661     
+ Misses       1533     1476      -57     
- Partials     1529     1530       +1     
Impacted Files Coverage Δ
Libplanet.Tests/Action/PolymorphicActionTest.cs 86.48% <ø> (+8.43%) ⬆️
Libplanet.Tests/Common/Action/DumbAction.cs 82.16% <ø> (-0.95%) ⬇️
Libplanet.Tests/Common/Action/MinerReward.cs 54.83% <ø> (-14.52%) ⬇️
Libplanet.Tests/Common/Action/ThrowException.cs 100.00% <ø> (+20.00%) ⬆️
Libplanet.Tests/Common/RenderRecord.cs 100.00% <ø> (ø)
Libplanet.Tests/Net/SwarmTest.Fixtures.cs 100.00% <ø> (ø)
Libplanet/Action/PolymorphicAction.cs 100.00% <ø> (+7.54%) ⬆️
Libplanet/Net/Swarm.cs 86.10% <0.00%> (ø)
Libplanet/Store/StoreExtensions.cs 50.00% <ø> (+5.71%) ⬆️
Libplanet/Blockchain/BlockChain.cs 90.83% <85.29%> (+0.34%) ⬆️
... and 23 more

@dahlia dahlia force-pushed the renderer branch 3 times, most recently from 3fe7884 to 99d9f97 Compare August 23, 2020 12:57
@dahlia dahlia changed the title WIP: IRenderer<T> and BlockChain<T>.Renderers WIP: Replace IAction.Render*() methods with IRenderer<T> Aug 23, 2020
@dahlia dahlia changed the title WIP: Replace IAction.Render*() methods with IRenderer<T> WIP: Replace IAction rendering methods with IRenderer<T> Aug 23, 2020
@dahlia dahlia force-pushed the renderer branch 3 times, most recently from 938739a to e03b2c9 Compare August 23, 2020 19:15
@dahlia dahlia changed the title WIP: Replace IAction rendering methods with IRenderer<T> WIP: Unify all state change events on BlockChain<T> into IRenderer<T> Aug 23, 2020
@dahlia dahlia changed the title WIP: Unify all state change events on BlockChain<T> into IRenderer<T> Unify all state change events on BlockChain<T> into IRenderer<T> Aug 23, 2020
@dahlia dahlia marked this pull request as ready for review August 23, 2020 21:58
const string endMessage =
"Invoked {MethodName}() for an action {ActionType} at block #{BlockIndex}";

if (context.Rehearsal)
Copy link
Member

Choose a reason for hiding this comment

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

Is there a case where context.Rehearsal is true during rendering?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we correctly implemented and our intention won't change at all there is indeed no such case. However, this is for the sake of easier debugging, so I thought it's useful.

/// An event which is invoked when the chain is reorged.
/// </summary>
public event EventHandler<ReorgedEventArgs> Reorged;
private event EventHandler<(Block<T> OldTip, Block<T> NewTip)> TipChanged;
Copy link
Member

Choose a reason for hiding this comment

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

This pull request introduces a new interface named IRenderer and replaces rendering methods of IAction and TipChanged/Reorged events on BlockChain with it.

Just curiosity... Is this change make replaces TipChanged event from BlockChain<T> to IRenderer<T>?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just curiosity... Is this change make replaces TipChanged event from BlockChain<T> to IRenderer<T>?

Yes!:

Besides rendering IActions, IRenderer<T> also replaces BlockChain<T>.TipChanged event (introduced in #517 & #526) with IRenderer<T>.RenderBlock() method, and BlockChain<T>.Reorged event (introduced in #945) with IRenderer<T>.RenderReorg() method. It means now all events regarding state changes on BlockChain<T> become unified into one interface IRenderer<T>.

(FYI I actually left BlockChain<T>.TipChanged event private for an internal use: cancelling undergoing mining when a new block is appended. However, still it is invisible from public surface.)

Copy link
Member

@riemannulus riemannulus Aug 24, 2020

Choose a reason for hiding this comment

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

Ah, I understand. Move rendering role from TipChanged event to IRenderer<T>.RenderBlock() . also TipChanged have only check changed tip blockchain itself. right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@riemannulus Right!

longfin
longfin previously approved these changes Aug 24, 2020
earlbread
earlbread previously approved these changes Aug 24, 2020
riemannulus
riemannulus previously approved these changes Aug 24, 2020
Because without the render option, the same behaviour can be achieved by
using non renderers.

See also planetarium#883
which is replaced by IRenderer<T>.BlockRender() method.
which is replaced by IRenderer<T>.RenderReorg() method.

See also planetarium#945
@dahlia
Copy link
Contributor Author

dahlia commented Aug 24, 2020

@planetarium/libplanet I fixed a small typo; please review this again!

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.

Extract rendering methods from IAction into a separated interface
6 participants