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

Add support for transactional state facet #67

Open
Johanny opened this issue May 29, 2019 · 3 comments
Open

Add support for transactional state facet #67

Johanny opened this issue May 29, 2019 · 3 comments

Comments

@Johanny
Copy link

Johanny commented May 29, 2019

Since the release of Orleans 2.1.0 grains now support transactions.

For a grain to use transactions it should be instanciated with a ITransactionalState<TState> facet:

public AccountGrain(
    [TransactionalState("balance", "TransactionStore")]
    ITransactionalState<Balance> balance)
{
    this.balance = balance ?? throw new ArgumentNullException(nameof(balance));
}

It would be great to be able to unit test grain with a transactionnal state facet with the test kit. Right now trying to get a grain with a ITransactionalState<TState> facet like so:

var grain = await Silo.CreateGrainAsync<AccountGrain>(Guid.NewGuid());

Is throwing this exception:

Orleans.Runtime.OrleansException : Attribute mapper Castle.Proxies.IAttributeToFactoryMapper`1Proxy failed to create a factory for grain type AccountGrain
   at Orleans.Runtime.ConstructorArgumentFactory.ArgumentFactory.GetFactory[TMetadata](IServiceProvider services, ParameterInfo parameter, IFacetMetadata metadata, Type type) in D:\build\agent\_work\23\s\src\Orleans.Runtime\Facet\ConstructorArgumentFactory.cs:line 90

Here is a naive implementation that fulfil the ITransactionalState interface and enable testing such grains:

class TestTransactionalState<TState> : ITransactionalState<TState>
    where TState : class, new()
{
    private readonly TState _state = new TState();

    public Task<TResult> PerformRead<TResult>(Func<TState, TResult> readFunction)
    {
        return Task.FromResult(readFunction(_state));
    }

    public Task<TResult> PerformUpdate<TResult>(Func<TState, TResult> updateFunction)
    {
        return Task.FromResult(updateFunction(_state));
    }
}

Standalone usage example:

var state = new TestTransactionalState<Balance>();
var grain = new AccountGrain(state);

This implementation works but something integrated to the test kit would be better.

@seniorquico
Copy link
Collaborator

This is very similar to #55. We can support constructor injection of ITransactionalState<TState> mock objects by registering our own implementation of IAttributeToFactoryMapper<TransactionalStateAttribute> in the silo's dependency injection container.

@seniorquico seniorquico self-assigned this Jun 2, 2019
@erikljung
Copy link

Any progress on this? Would be a great feature!

@seniorquico
Copy link
Collaborator

@erikljung Not directly. I have a branch that adds the needed support for constructor injection, but I've only applied it to the state facet interfaces/classes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants