Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 01:50
    ipkaq starred dotnet/orleans
  • Apr 07 22:39
    PiotrJustyna starred dotnet/orleans
  • Apr 07 21:49
    sergeybykov assigned #6467
  • Apr 07 21:01
    kehigginbotham commented #6463
  • Apr 07 20:55
    ReubenBond synchronize #6468
  • Apr 07 20:54
    ReubenBond commented #6463
  • Apr 07 20:52

    sergeybykov on 3.2.0

    Dont use iowait in cpu calcs on… TLS: specify an application pro… Change the error about not supp… and 3 more (compare)

  • Apr 07 20:30
    ReubenBond opened #6468
  • Apr 07 20:30
    ReubenBond milestoned #6468
  • Apr 07 20:30
    kehigginbotham commented #6463
  • Apr 07 20:20

    ReubenBond on 3.1.5

    Allow GatewayManager initializa… (compare)

  • Apr 07 20:19
    ReubenBond commented #6463
  • Apr 07 18:57
    adyada edited #6467
  • Apr 07 18:52
    adyada edited #6467
  • Apr 07 18:51
    adyada opened #6467
  • Apr 07 18:40

    sergeybykov on 3.1.5

    TLS: specify an application pro… Change the error about not supp… Update obsoletion warning for I… and 1 more (compare)

  • Apr 07 18:30
    kehigginbotham commented #6463
  • Apr 07 18:25
    kehigginbotham commented #6463
  • Apr 07 17:55
    sergeybykov milestoned #6465
Max Shnurenok
@MaxCrank
Hi again guys, our integration attempts are on the way, so another question appeared. Let's say we have a data structure representing an Account which has internal ID as well as several more IDs bound to external systems. E.g. Account has Id as well as ExternalId1, ExternalId2 etc. And in different use-cases we have only one of these IDs as an input information to get an Account... but if we use Orleans to operate an Account through the Grain, we need uniformed access to leverage the reentrance and other features properly, i.e. we need to use exactly the same ID. I see several ways of handling this, each of them including a need to make intermediate storage calls for getting internal Account ID by any of external IDs for the same entity, which isn't really good. Formally, we may extract each external info into separate entities to go along with "one entity - single ID" (and also following "best practices"), but it also won't come without a price... Maybe somebody had the same case?
Samir Mowade
@sammym1982

Without persistent state you can't guarantee that there are single instances for something which is purely in-memory.

@ReubenBond can you expand on above statement from :point_up: January 20, 2020 9:06 AM
By Persistent state did you meant grain which are having state using [PersistentState] or similar attribute. I wanted to make sure I am reading it wrong :) Not related to original question but wanted to understand more if there are some nuances which I should be aware of.

Reuben Bond
@ReubenBond

The in-built grain directory implementation in Orleans is eventually-consistent, @sammym1982. That can become an issue when the cluster isn't in a steady state and calls for the same grain come in quick success - if nothing is done to mitigate it. The mitigation is persistent state. Any time a grain activation tries to write state, a concurrency check is performed to make sure the grain activation has the latest state (i.e, it has seen all previous writes). If that is not true then an exception is thrown and the grain is deactivating, making the convergence quicker.

Without that mitigation (or something to a similar effect), it's possible for multiple activations of the grain to exist simultaneously for a short period of time. Those duplicates are proactively killed as the directory converges.

A similar mitigation is to use leasing. Strong single-activation guarantees are something which we intend to add as an optional feature (it comes at a cost, but it could be opted into on a per-grain-type basis)
Samir Mowade
@sammym1982
Thanks @ReubenBond Does the runtime look for any particular etag concurrency exception in such case or any exception type during WriteStateAsync will trigger that correction?
Reuben Bond
@ReubenBond
Yes, that's right
David Christensen
@OracPrime
Thank you @ReubenBond . The problem I had was that I was using LocalClustering and had failed to specify a primary silo. So it now looks like (there's more after this, but this is the crucial bit)
ISiloHostBuilder builder = new SiloHostBuilder()
.AddGrainControl()
.UseLocalhostClustering(cBaseSiloPort+instanceNum, cBaseGatewayPort+instanceNum,new IPEndPoint(IPAddress.Loopback, cBaseSiloPort))
Previously I was lacking the third parameter. With that the silos "play nicely together" and stuff works.
Harald Schult Ulriksen
@Ulriksen
@MaxCrank we have a case where several external IDs that can point to our internal ID (added bonus - the external IDs can change). We use what we call "IdMapper" for this. This grain map external id to our internal id (we also have a reverse mapper). Since this is used at the edge of our API (most API calls to our system use external id's) we've used a cache pattern where we have stateless IdMapper grains running in each silo which loads the mapping into memory from the the persistent IdMapper grain. We then use the internalID from there on and try to only use this in our internal actor model.
Max Shnurenok
@MaxCrank
@Ulriksen Thank you very much for the response, looks like no silver bullet then :) One of the things we discussed is literally the same thing - making a generic ID provider abstraction based on some kind of cache under the hood and implementing the specific providers as needed, starting with the one for Account entities...
Harald S. Ulriksen
@hsulriksen_twitter
@MaxCrank another option is to use a state store which is quaryable, such as Cosmos/Mongo or SQL and use that as the mapping cache
Reuben Bond
@ReubenBond
dotnet/orleans#6250 << we will finally support directly configuring ISiloBuilder & IHostBuilder from TestClusters ☺ The implementation is very simple in the end.
Tom Nelson
@Zeroshi
hi @sergeybykov , I was checking in to see if you had a chance to read that essay.
Kyle Dodson
@seniorquico

has anyone encountered the following error before?

Exc level 0: Orleans.Runtime.OrleansException: Reminder Service is still initializing and it is taking a long time. Please retry again later.

Sergey Bykov
@sergeybykov

@Zeroshi @COCPORN

why couldnt you add an if statement to determine if it should run? @sergeybykov any idea?

Early on, we were concerned about deactivating grains under perceived memory pressure, primarily because it wasn't clear how to measure what amount of memory is actually being used by the app logic as opposed to the amount of Gen2 memory garbage accumulated since the last Gen2 pass of the memory manager. I suspect it should be more clear these days.
It's a bit more than adding an if statement because grains activations are tracked in buckets, from most recently used ones to LRU. Other than that, at least conceptually, it could be a matter of checking for memory pressure (if configured) upon every activation collection cycle and adding an oldest bucket or two for collection.

Sergey Bykov
@sergeybykov

@Zeroshi

hi @sergeybykov , I was checking in to see if you had a chance to read that essay.

Sorry, I dropped the ball when we suddenly got some snow. I read it now. I think it'd be better for us to chat thematically over Teams/Skype than for me to try to type the same thoughts, and then for us to go back and forth. A voice dialog is an efficient means of arriving to something. 🙂

Lars Thomas Denstad
@COCPORN
@sergeybykov Yes, it was hyperbole from me. About the buckets, perhaps I've misunderstood how they work. It looks to just be sorted on expiry time, and then I suppose any grain that has activity moves itself to another bucket based on the time to live configuration. I could take a stab at implementing my suggestion, as I think the amount of work needed to have something that is useful (or can at least be evaluated for usefulness) isn't that big.
Veikko Eeva
@veikkoeeva
Veikko Eeva
@veikkoeeva
Panu Oksala
@PanuOksala_twitter
I'm running heterogeneous cluster with multiple Silos and it seems to be that all the Silos need to reference entities that are exposed in grain interfaces, is this true?
basically I need to have shared entity library that is referenced from all the Silos. This breaks the microservice architecture
If I don't reference this shared library from one the Silos, the grain calls may crash in binary serialization, because the passing through silo don't know about entities
Lars Thomas Denstad
@COCPORN
Perhaps I am misunderstanding, I am not sure what you mean by heterogeneous cluster if the silos are different. How do you expect the silo to be able to deserialize something that it doesn't have an implementation class for it?
Panu Oksala
@PanuOksala_twitter
I except that when calling Silo that does not have implementation for the actor, it would pass it to another Silo which contains the implementation for actor, without deserializing the method parameters
Veikko Eeva
@veikkoeeva
Heh, mentioned Orleans indirectly at https://twitter.com/hiddenmarkov/status/1219288129716334592 and https://twitter.com/_dotnetbot_ picked it up. :D Though the truth is, I believe, Orleans and actor model in general, could fit even complex CPS deployments. There just are gnarly problems otherwise to consider.
Panu Oksala
@PanuOksala_twitter

Silo A hosts Grain A1
Silo B hosts Grain B1 which has method DoSomething(Customer customer)

I call grain B1 from clusterclient, the invocation goes to A1 which deserializes the message (and crashes because it does not know about Customer) and does not resend the message to B1

Lars Thomas Denstad
@COCPORN
@PanuOksala_twitter I don't know about this kind of behavior. Is it a documented feature?
Panu Oksala
@PanuOksala_twitter
If I add Customer class into shared dll and add reference to Silo A, everything works.
Documentation says: All silos should reference interfaces of all grain types of the cluster, but grain classes should only be referenced by the silos that will host them.
What I have tested, this is actually not true. The method parameter type is the problem, not the grain interfaces.
Lars Thomas Denstad
@COCPORN
Where is this documentation? I am curious.
Lars Thomas Denstad
@COCPORN
Thanks! I'll look at it. I am sorry, I am unfamiliar with this feature, so I suspect I cannot really be helpful.
Where do you run the codegeneration?
Panu Oksala
@PanuOksala_twitter
we use the codegenerator.msbuild nuget package, which creates the files during build.
that package is referenced at least in the silo hosts
Lars Thomas Denstad
@COCPORN
Is it in the interface assembly, tho?
Thanks for the tip about this feature, BTW. It has passed me by completely.
Panu Oksala
@PanuOksala_twitter
Yes
burgerTo
@burgerTo

Hi,
i have a question regarding async running methods.

This is a examplecode of a GrainMethod:

public Task GrainMethod()
{
_anotherGrain = GrainFactory.GetGrain<IBasicMeasurementDevice>(guid);

_anotherGrain.AnotherGrainMethod().ContinueWith(task =>
{
    //modify private members in Grain;
}, TaskContinuationOptions.OnlyOnFaulted);

}

I want to run the "AnotherGrain" Method without awaiting for it. But if there occurs a exception, I want to modifie the state of the caller grain.
Could this solution lead to race conditions?

oleggolovkovuss
@oleggolovkovuss
Hello, does anyone know what should I use instead of
options.Invariant = "MySql.Data.MySqlClient"; //this was working with mysql 5.6
with MySql 8?
oleggolovkovuss
@oleggolovkovuss
actually the invariant seems fine, it doesn't like the creation of stored procedures now for some reason
oleggolovkovuss
@oleggolovkovuss
ok, my error was because of this line https://github.com/dotnet/orleans/blob/master/src/AdoNet/Orleans.Persistence.AdoNet/MySQL-Persistence.sql#L92 though the exception message was saying there's wrong syntax in a diffrent location omg, thanks all :D
Panu Oksala
@PanuOksala_twitter
@COCPORN I have an example project available that verifies this issue
Sergey Bykov
@sergeybykov

@COCPORN

@sergeybykov Yes, it was hyperbole from me. About the buckets, perhaps I've misunderstood how they work. It looks to just be sorted on expiry time, and then I suppose any grain that has activity moves itself to another bucket based on the time to live configuration. I could take a stab at implementing my suggestion, as I think the amount of work needed to have something that is useful (or can at least be evaluated for usefulness) isn't that big.

Yes, when a grain is invoked, it gets moved to the most recent bucket, unless it's already there. If you are willing to take a stab at it, we'll be happy to help.

@PanuOksala_twitter http://dotnet.github.io/orleans/Documentation/clusters_and_clients/heterogeneous_silos.html says: "All silos should reference interfaces of all grain types of the cluster, but grain classes should only be referenced by the silos that will host them." That also implies that any serializable types that could be sent as arguments should be referenced by all silos. Maybe worth adding such a statement to the doc to prevent confusion.
Sergey Bykov
@sergeybykov
@burgerTo I believe what you are trying to do will generally work, with all the potential implications of not awating an outgoing call - the caller grain might get deactivated before the response arrives, etc.
David Christensen
@OracPrime
Is there any documentation on custom placement strategies? There are the examples inside the Orleans repo, but I feel like I'm reverse engineering...
Reuben Bond
@ReubenBond
There aren't yet, @OracPrime - but they would be welcome :)
David Christensen
@OracPrime
Yes, wouldn't they :)
Barry Briggs
@barrybriggs
Ref the docs on external tasks: https://dotnet.github.io/orleans/Documentation/grains/external_tasks_and_grains.html I'm assuming from reading that I could use this method to call out from a grain to a very-long-running-task (like a Python interpreter training an ML model) and have it periodically call back into a grain?
(Just want to check before writing a bunch of code :-))