static void Main(string[] args) { List <long> data = new List <long>(); DateTime timeBegin = DateTime.Now; //var generator = new IdGenerator(0); var epoch = new DateTime(2020, 7, 22, 0, 0, 0, DateTimeKind.Utc); var structure = new IdStructure(45, 2, 16); var options = new IdGeneratorOptions(structure, new DefaultTimeSource(epoch)); var generator = new IdGenerator(0, options); for (int i = 0; i < 100000000; i++) { var id = generator.CreateId(); data.Add(id); //Console.WriteLine($"生成id:{id}"); } DateTime timeEnd = DateTime.Now; TimeSpan span = timeEnd.Subtract(timeBegin); data.Add(data.Last()); Console.WriteLine($"添加一个测试数据后:{data.Count}"); data = data.Distinct().ToList(); Console.WriteLine($"取出重复数据后:{data.Count}"); Console.WriteLine($"耗时:{span.TotalSeconds}"); Console.WriteLine($"平均每秒产生:{data.Count / span.TotalSeconds}"); Console.ReadLine(); }
public void FromId_Returns_CorrectValue() { var s = new IdStructure(42, 8, 13); var epoch = new DateTimeOffset(2018, 7, 31, 14, 48, 2, TimeSpan.FromHours(2)); // Just some "random" epoch... var ts = new MockTimeSource(5, TimeSpan.FromSeconds(7), epoch); // Set clock at 5 ticks; each tick being 7 seconds... // Set generator ID to 234 var g = new IdGenerator(234, new IdGeneratorOptions(s, ts)); // Generate a bunch of id's long id = 0; for (var i = 0; i < 35; i++) { id = g.CreateId(); } var target = g.FromId(id); Assert.AreEqual(34, target.SequenceNumber); // We generated 35 id's in the same tick, so sequence should be at 34. Assert.AreEqual(234, target.GeneratorId); // With generator id 234 Assert.AreEqual(epoch.Add(TimeSpan.FromSeconds(5 * 7)), target.DateTimeOffset); // And the clock was at 5 ticks, with each tick being // 7 seconds (so 35 seconds from epoch) // And epoch was 2018-7-31 14:48:02 +02:00... }
public static void Initialize(IdGenSettings settings) { //var epoch = new DateTime(2020, 12, 22, 0, 0, 0, DateTimeKind.Utc); var structure = new IdStructure(settings.TimestampBits, settings.GeneratorIdBits, settings.SequenceBits); var options = new IdGeneratorOptions(structure, new DefaultTimeSource(settings.Epoch)); StaticIdGen.IdGen = new IdGenDistributedId(settings.MachineId, options); }
public void GeneratorId_ShouldBePresent_InID2() { // We setup our generator so that the time is 0 and generator id equals 4095 so that all 12 bits are set // for the generator. var ts = new MockTimeSource(); var s = new IdStructure(40, 12, 11); // We use a custom IdStructure with 12 bits for the generator this time var g = new IdGenerator(4095, new IdGeneratorOptions(s, ts)); // Make sure all expected bits are set Assert.AreEqual(-1 & ((1 << 12) - 1), g.Id); Assert.AreEqual((1 << 12) - 1 << 11, g.CreateId()); }
public IdManager() { // Fun fact: This is the exact moment that SpookVooper was terminated // which led to the development of Valour becoming more than just a side // project. Viva la Vooperia. var epoch = new DateTime(2021, 1, 11, 4, 37, 0); var structure = new IdStructure(45, 10, 8); var options = new IdGeneratorOptions(structure, new DefaultTimeSource(epoch)); Generator = new IdGenerator(0, options); }
public SnowflakeEngine() { Epoch = new DateTime(2020, 7, 30, 0, 0, 0, DateTimeKind.Utc); //This is written @ 11:58 PM, 30/7/2020 // Create an ID with 31 Bit for TimeStamp, 1 Bits for GeneratorID and 31 Bits for Sequence var IDStructure = new IdStructure(31, 1, 31); var Options = new IdGeneratorOptions(IDStructure, new DefaultTimeSource(Epoch)); Generator = new IdGenerator(1, Options); }
public void CreateId_Waits_OnSequenceOverflow() { // Use timesource that generates a new tick every 10 calls to GetTicks() var ts = new MockAutoIncrementingIntervalTimeSource(10); var s = new IdStructure(61, 0, 2); var g = new IdGenerator(0, new IdGeneratorOptions(idStructure: s, timeSource: ts, sequenceOverflowStrategy: SequenceOverflowStrategy.SpinWait)); // We have a 2-bit sequence; generating 4 id's in a single time slot - wait for other then Assert.AreEqual(0, g.CreateId()); Assert.AreEqual(1, g.CreateId()); Assert.AreEqual(2, g.CreateId()); Assert.AreEqual(3, g.CreateId()); Assert.AreEqual(4, g.CreateId()); // This should trigger a spinwait and return the next ID Assert.AreEqual(5, g.CreateId()); }
public void CreateId_Throws_OnSequenceOverflow() { var ts = new MockTimeSource(); var s = new IdStructure(41, 20, 2); var g = new IdGenerator(0, new IdGeneratorOptions(idStructure: s, timeSource: ts)); // We have a 2-bit sequence; generating 4 id's shouldn't be a problem for (var i = 0; i < 4; i++) { Assert.AreEqual(i, g.CreateId()); } // However, if we invoke once more we should get an SequenceOverflowException g.CreateId(); }
public void TryCreateId_Returns_False_OnSequenceOverflow() { var ts = new MockTimeSource(); var s = new IdStructure(41, 20, 2); var g = new IdGenerator(0, new IdGeneratorOptions(idStructure: s, timeSource: ts)); // We have a 2-bit sequence; generating 4 id's shouldn't be a problem for (var i = 0; i < 4; i++) { Assert.IsTrue(g.TryCreateId(out var _)); } // However, if we invoke once more we should get an SequenceOverflowException // which should be indicated by the false return value Assert.IsFalse(g.TryCreateId(out var _)); }
static IdGenerator() { if (!IdGenGlobalState.IsCreated) { throw new InvalidOperationException("IdGenerator is not initialized"); } var structure = new IdStructure(44, 6, 13); Generator = new IdGen.IdGenerator(IdGenGlobalState.InstanceId, new IdGeneratorOptions( idStructure: structure, timeSource: new DefaultTimeSource(IdGenGlobalState.Epoch), sequenceOverflowStrategy: SequenceOverflowStrategy.SpinWait)); Console.WriteLine("Max. generators : {0}", structure.MaxGenerators); Console.WriteLine("Id's/ms per generator : {0}", structure.MaxSequenceIds); Console.WriteLine("Wraparound date : {0:O}", structure.WraparoundDate(Generator.Options.TimeSource.Epoch, Generator.Options.TimeSource)); }
public JsonResult AddBill(string name, string address, string phone, string email, int payment) { try { Bill bill = new Bill(); //Declare snowflake algorithm DateTime epoch = new DateTime(2021, 1, 1, 0, 0, 0, DateTimeKind.Utc); //41 bit for time //12 bit for number of shard //10 bit for sequence IdStructure structure = new IdStructure(41, 12, 10); IdGeneratorOptions option = new IdGeneratorOptions(structure, new DefaultTimeSource(epoch)); IdGenerator generator = new IdGenerator(0, option); //create new id and declare properties to bill long billID = generator.CreateId(); bill.BillID = billID; bill.userName = name; bill.address = address; bill.phoneNumber = phone; bill.email = email; bill.payment = payment; bill.status = 1; bill.orderTime = DateTime.Now; //email content string content = $"You have successfully booked your order, the ready-made product will be delivered within {DateTime.Now.AddDays(3).Date} to {DateTime.Now.AddDays(7).Date}<br/><br/>"; content += $"Order ID: {billID}<br/><br/>"; //head row of table content += "<table><tr style=\"color: white; background-color: #7fad39;\"><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\">Product</td><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\">Price</td><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\">Quantity</td><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\">Total</td></tr>"; decimal totalValue = 0; //is loged User if (Session["user"] == null) { //didn't log in case, storage cart in cookies Dictionary <string, int> cart; //check is exsisted cart in cookies if (Session["cart"] != null) { //exsisted case, pick up it cart = (Dictionary <string, int>)Session["cart"]; Dictionary <string, int> .KeyCollection keys = cart.Keys; //add bill to database foreach (string key in keys) { bill.productid = Int32.Parse(key); bill.quantity = cart[key]; Product p = db.Products.Find(bill.productid = Int32.Parse(key)); bill.amount = p.price; //add into bill db.Bills.Add(bill); db.SaveChanges(); //add middle row of table decimal total = p.price * cart[key]; content += $"<tr style=\"background - color: #eeeeee;\"><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\">{p.title}</td><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\">{p.price.ToString("C")}</td><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\">{cart[key]}</td><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\">{total.ToString("C")}</td>"; totalValue += total; } Session.Remove("cart"); } else { //in null case of cart return(Json("Please put item into cart before check out!", JsonRequestBehavior.AllowGet)); } } else { //loged in case Account account = db.Accounts.Find(Int32.Parse(Session["user"].ToString())); bill.userid = account.userID; //load cart infor from database List <Cart> carts = db.Carts.ToList().Select(cart => new Cart { cartid = cart.cartid, userid = cart.userid, productid = cart.productid, quantity = cart.quantity, Account = db.Accounts.Find(cart.userid), Product = db.Products.Find(cart.productid) }).Where(c => c.userid == account.userID).ToList(); //check is exsisted any item in cart in database if (carts.Count > 0) { foreach (Cart cart in carts) { bill.productid = cart.productid; bill.quantity = cart.quantity; bill.amount = cart.Product.price; //add bill db.Bills.Add(bill); //add middle row of table decimal total = cart.Product.price * cart.quantity; content += $"<tr style=\"background - color: #eeeeee;\"><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\">{cart.Product.title}</td><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\">{cart.Product.price.ToString("C")}</td><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\">{cart.quantity}</td><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\">{total.ToString("C")}</td>"; totalValue += total; //remove item from cart db.Carts.Remove(db.Carts.Find(cart.cartid)); db.SaveChanges(); } } else { //in null case of cart return(Json(new { type = 2, message = "Please put item into cart before check out!" }, JsonRequestBehavior.AllowGet)); } } Session["tempBillID"] = billID; //last row of table content += $"<tr style=\"background-color: #F5F5F5;\"><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\"></td><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\"></td><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\">Total order value</td><td style=\"padding: 5px 10px 5px 10px; font-size: 15px;\">{totalValue.ToString("C")}</td></tr></table>"; try { //send email to user MailAddress senderEmail = new MailAddress("*****@*****.**", "BookStore"); MailAddress receiverEmail = new MailAddress(email, "Receiver"); string password = "******"; string subject = "Order successfull"; string body = content; SmtpClient smtp = new SmtpClient { Host = "smtp.gmail.com", Port = 587, EnableSsl = true, DeliveryMethod = SmtpDeliveryMethod.Network, UseDefaultCredentials = false, Credentials = new NetworkCredential(senderEmail.Address, password) }; using (MailMessage mess = new MailMessage(senderEmail, receiverEmail) { Subject = subject, Body = body }) { mess.IsBodyHtml = true; smtp.Send(mess); } return(Json(new { type = 1, message = "Check Out Success!" }, JsonRequestBehavior.AllowGet)); } catch { return(Json(new { type = 2, message = "Send email fail!" }, JsonRequestBehavior.AllowGet)); } } catch { return(Json(new { type = 2, message = "Check Out Fail!" }, JsonRequestBehavior.AllowGet)); } }
public void ConfigureServices(IServiceCollection services) { Log.Information("Startup::ConfigureServices"); try { services.AddControllers( opt => { //Custom filters can be added here //opt.Filters.Add(typeof(CustomFilterAttribute)); //opt.Filters.Add(new ProducesAttribute("application/json")); } ).SetCompatibilityVersion(CompatibilityVersion.Version_3_0); #region "API versioning" //API versioning service services.AddApiVersioning( o => { //o.Conventions.Controller<UserController>().HasApiVersion(1, 0); o.AssumeDefaultVersionWhenUnspecified = true; o.ReportApiVersions = true; o.DefaultApiVersion = new ApiVersion(1, 0); o.ApiVersionReader = new UrlSegmentApiVersionReader(); } ); // format code as "'v'major[.minor][-status]" services.AddVersionedApiExplorer( options => { options.GroupNameFormat = "'v'VVV"; //versioning by url segment options.SubstituteApiVersionInUrl = true; }); #endregion #region Database // Register Database Entity Maps services.AddSingleton <IEntityTypeMap, UserMap>(); services.AddSingleton <IEntityTypeMap, DroneMap>(); services.AddSingleton <IEntityTypeMap, MissionMap>(); services.AddSingleton <IEntityTypeMap, CompanyAccountMap>(); services.AddSingleton <IEntityTypeMap>(new BaseEntityMap <DroneCommands>()); services.AddSingleton <IEntityTypeMap>(new BaseEntityMap <DroneNetworkSettings>()); services.AddSingleton <IEntityTypeMap>(new BaseEntityMap <DroneOnvifSettings>()); services.AddSingleton <IEntityTypeMap>(new BaseEntityMap <GeoArea>()); services.AddSingleton <IEntityTypeMap>(new BaseEntityMap <GeoPoint>()); services.AddSingleton <IEntityTypeMap>(new BaseEntityMap <PatrolConfig>()); services.AddSingleton <IEntityTypeMap>(new BaseEntityMap <Drone>()); services.AddSingleton <IEntityTypeMap>(new BaseEntityMap <ObjectDetection>()); services.AddSingleton <IEntityTypeMap>(new BaseEntityMap <PlannedRoute>()); services.AddSingleton <IEntityTypeMap>(new BaseEntityMap <StatusReport>()); //DB service if (Configuration["ConnectionStrings:UseInMemoryDatabase"] == "True") { services.AddDbContext <DefaultDbContext>(opt => opt.UseInMemoryDatabase("TestDB-" + Guid.NewGuid().ToString())); } else { services.AddDbContext <DefaultDbContext>(options => options.UseNpgsql( Configuration["ConnectionStrings:Moonlimit.DroneAPIDB"], o => o.UseNetTopologySuite()) , ServiceLifetime.Transient); } #endregion #region "Authentication" if (Configuration["Authentication:UseIdentityServer4"] == "False") { //JWT API authentication service services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = Configuration["Jwt:Issuer"], ValidAudience = Configuration["Jwt:Issuer"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])) }; } ); } else { //Identity Server 4 API authentication service services.AddAuthorization(); //.AddJsonFormatters(); services.AddAuthentication("Bearer") .AddIdentityServerAuthentication(option => { option.Authority = Configuration["Authentication:IdentityServer4IP"]; option.RequireHttpsMetadata = false; //option.ApiSecret = "secret"; option.ApiName = "Moonlimit.DroneAPI"; //This is the resourceAPI that we defined in the Config.cs in the AuthServ project (apiresouces.json and clients.json). They have to be named equal. }); } #endregion #region "CORS" // include support for CORS // More often than not, we will want to specify that our API accepts requests coming from other origins (other domains). When issuing AJAX requests, browsers make preflights to check if a server accepts requests from the domain hosting the web app. If the response for these preflights don't contain at least the Access-Control-Allow-Origin header specifying that accepts requests from the original domain, browsers won't proceed with the real requests (to improve security). services.AddCors(options => { options.AddPolicy("CorsPolicy-public", builder => builder.AllowAnyOrigin() //WithOrigins and define a specific origin to be allowed (e.g. https://mydomain.com) .AllowAnyMethod() .AllowAnyHeader() //.AllowCredentials() .Build()); }); #endregion #region "MVC and JSON options" //mvc service (set to ignore ReferenceLoopHandling in json serialization like Users[0].Account.Users) //in case you need to serialize entity children use commented out option instead services.AddMvc(option => option.EnableEndpointRouting = false) .AddNewtonsoftJson(options => { options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; }); //NO entity classes' children serialization //.AddNewtonsoftJson(ops => //{ // ops.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize; // ops.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore; //}); //WITH entity classes' children serialization #endregion #region "DI code" //ID Generator var epoch = new DateTime(2021, 1, 1, 0, 0, 0, DateTimeKind.Utc); // Create an ID with 31 (68 years if measured in seconds) bits for timestamp, 16 for generator-id and 16 for sequence(65536 per sec.) var structure = new IdStructure(31, 16, 16); // Prepare options var options = new IdGeneratorOptions(structure, new DefaultTimeSource(epoch, TimeSpan.FromSeconds(1.0)), SequenceOverflowStrategy.SpinWait); services.AddSingleton(new IdGenerator(0, options)); //Gen0 is for testing //general unitofwork injections services.AddTransient <IUnitOfWork, UnitOfWork>(); //services injections services.AddTransient(typeof(CompanyAccountService <,>), typeof(CompanyAccountService <,>)); services.AddTransient(typeof(UserService <,>), typeof(UserService <,>)); services.AddTransient(typeof(CompanyAccountServiceAsync <,>), typeof(CompanyAccountServiceAsync <,>)); services.AddTransient(typeof(UserServiceAsync <,>), typeof(UserServiceAsync <,>)); // SetAdditionalDIServices(services); //...add other services // services.AddTransient(typeof(IService <,>), typeof(GenericService <,>)); services.AddTransient(typeof(IServiceAsync <,>), typeof(GenericServiceAsync <,>)); services.AddHttpContextAccessor(); services.AddScoped <IClaimsData, HttpClaimsData>(); services.AddScoped <IClaimValidator <Drone>, BasicClaimValidator <Drone> >(); services.AddScoped <IClaimValidator <DroneNetworkSettings>, BasicClaimValidator <DroneNetworkSettings> >(); services.AddScoped <IClaimValidator <Mission>, BasicClaimValidator <Mission> >(); #endregion //data mapper services configuration services.AddAutoMapper(typeof(MappingProfile)); #region "Swagger API" //Swagger API documentation services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Moonlimit.DroneAPI API", Version = "v1" }); c.SwaggerDoc("v2", new OpenApiInfo { Title = "Moonlimit.DroneAPI API", Version = "v2" }); //In Test project find attached swagger.auth.pdf file with instructions how to run Swagger authentication c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme() { Description = "Authorization header using the Bearer scheme", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey }); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Id = "Bearer", //The name of the previously defined security scheme. Type = ReferenceType.SecurityScheme } }, new List <string>() } }); //c.DocumentFilter<api.infrastructure.filters.SwaggerSecurityRequirementsDocumentFilter>(); }); #endregion } catch (Exception ex) { Log.Error(ex.Message); } }
private static async Task <ISiloHost> CreateSilo() { var conf = new RedisConfiguration() { AbortOnConnectFail = true, Hosts = new RedisHost[] { new RedisHost { Host = Configuration.GetSection("RedisCache")["Connection"], Port = int.Parse(Configuration.GetSection("RedisCache")["Port"]) } }, AllowAdmin = true, ConnectTimeout = 1000, ServerEnumerationStrategy = new ServerEnumerationStrategy() { Mode = ServerEnumerationStrategy.ModeOptions.All, TargetRole = ServerEnumerationStrategy.TargetRoleOptions.Any, UnreachableServerAction = ServerEnumerationStrategy.UnreachableServerActionOptions.Throw } }; var builder = new SiloHostBuilder() .Configure <ClusterOptions>(options => { options.ClusterId = Configuration.GetSection("Orleans")["ClusterId"]; options.ServiceId = Configuration.GetSection("Orleans")["ServiceId"]; }) .Configure <SchedulingOptions>(options => { options.AllowCallChainReentrancy = true; options.PerformDeadlockDetection = true; }) .Configure <SerializationProviderOptions>(options => { options.SerializationProviders.Add(typeof(ProtobufNetSerializer)); options.FallbackSerializationProvider = typeof(ProtobufNetSerializer); }) .Configure <EndpointOptions>(options => options.AdvertisedIPAddress = IPAddress.Loopback) .UseMongoDBClient(Configuration.GetSection("Orleans")["Connection"]) .UseMongoDBReminders(options => { options.DatabaseName = Configuration.GetSection("Orleans")["Database"]; options.CreateShardKeyForCosmos = false; }) .UseMongoDBClustering(c => { c.DatabaseName = Configuration.GetSection("Orleans")["Database"]; c.CreateShardKeyForCosmos = false; }) .AddMongoDBGrainStorageAsDefault(c => c.Configure(options => { options.DatabaseName = Configuration.GetSection("Orleans")["Database"]; options.CreateShardKeyForCosmos = false; })) .AddMongoDBGrainStorage("PubSubStore", options => { options.DatabaseName = Configuration.GetSection("Orleans")["Database"]; options.CreateShardKeyForCosmos = false; }) .ConfigureLogging(builder => { builder.AddSerilog(new LoggerConfiguration() .Enrich.WithMachineName() .ReadFrom.Configuration(Configuration) .CreateLogger()); }) .AddStartupTask <NStartupTask>() .ConfigureApplicationParts(parts => { parts.AddFromApplicationBaseDirectory().WithReferences(); }) //.AddApplicationPart(typeof(Node).Assembly).WithReferences()) .ConfigureServices(services => { services.AddIdGenerator(x => { string appIdStr = Configuration.GetSection("IdGen")["AppId"]; if (!ushort.TryParse(appIdStr, out ushort appid)) { throw new Exception("Please config appid in 'config.json'"); } x.AppId = appid; x.GeneratorOptions = new IdGeneratorOptions(); // Let's say we take april 1st 2020 as our epoch var epoch = DateTime.Parse(Configuration.GetSection("IdGen")["Epoch"]); byte timestampBits = byte.Parse(Configuration.GetSection("IdGen")["TimestampBits"]); byte generatorIdBits = byte.Parse(Configuration.GetSection("IdGen")["GeneratorIdBits"]); byte sequenceBits = byte.Parse(Configuration.GetSection("IdGen")["SequenceBits"]); // Create an ID with 45 bits for timestamp, 2 for generator-id // and 16 for sequence var structure = new IdStructure(timestampBits, generatorIdBits, sequenceBits); // Prepare options x.GeneratorOptions = new IdGeneratorOptions(structure, new DefaultTimeSource(epoch)); }); services.AddStackExchangeRedisExtensions <CacheSerializer>(conf); string connection = Configuration.GetSection("MongoPersist")["Connection"]; services.AddSingleton <MongoDB.Driver.IMongoClient>(s => new MongoDB.Driver.MongoClient(connection)); services.AddSingleton <IAccountDB, AccountDB>(); services.AddSingleton <IRealmDB, RealmDB>(); services.AddSingleton <IEntityDB, EntityDB>(); }) //need to configure a grain storage called "PubSubStore" for using streaming with ExplicitSubscribe pubsub type //.AddMemoryGrainStorage("PubSubStore") //Depends on your application requirements, you can configure your silo with other stream providers, which can provide other features, //such as persistence or recoverability. For more information, please see http://dotnet.github.io/orleans/Documentation/Orleans-Streams/Stream-Providers.html .AddSimpleMessageStreamProvider(StreamProviders.AgentProvider); var host = builder.Build(); await host.StartAsync(); return(host); }