public ControlTowerActor() { // CosmosDb methods var cdb = new CosmosDB(); // get info about the flight var icao = Context.ActorOf <ICAOLookupActor>(); // register actor type as a sharded entity region = ClusterSharding.Get(Context.System).Start( typeName: "FlightActor", entityProps: Props.Create <FlightActor>(), settings: ClusterShardingSettings.Create(Context.System), messageExtractor: new MessageExtractor()); // get a set of data readings Receive <DeviceReading>(r => { foreach (var a in r.aircraft.Where(z => !string.IsNullOrWhiteSpace(z.flight))) { if (!initedActors.ContainsKey(a.flight)) { initedActors.Add(a.flight, DateTime.Now); var cos = Context.ActorOf(CosmosSaveActor.Props(cdb)); region.Tell(new ShardEnvelope(shardId: "1", entityId: a.flight, message: new FlightActor.FlightActorInit(cos, a.flight, icao))); } // create message for flight actor var req = new FlightActor.FlightDataRequest() { deviceId = r.deviceId, flightData = a, now = r.now }; // send message to entity through shard region region.Tell(new ShardEnvelope(shardId: "1", entityId: a.flight, message: req)); initedActors[a.flight] = DateTime.Now; } }); }
public SubCoordinatorActor() { // CosmosDb methods var cdb = new CosmosDB(); // get info about the flight var icao = Context.ActorOf <ICAOLookupActor>(); // flight code => Actor Dictionary <string, IActorRef> flightActors = new Dictionary <string, IActorRef>(); // flight code => last message processed Dictionary <string, DateTime> flightExpiry = new Dictionary <string, DateTime>(); // clear out old actors Context.System.Scheduler.ScheduleTellRepeatedly(TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(15), Self, new ExpireActors(), Self); // group of readings Receive <DeviceReading>(r => { // foreach plane in current reading -- ignoring those w/o flight code foreach (var dr in r.aircraft.Where(z => !string.IsNullOrWhiteSpace(z.flight))) { // create message for flight actor var req = new FlightActor.FlightDataRequest() { deviceId = r.deviceId, flightData = dr, now = r.now }; // if not started up, then do so now if (!flightActors.ContainsKey(dr.flight)) { var cos = Context.ActorOf(CosmosSaveActor.Props(cdb)); // flightActors.Add(dr.flight, Context.ActorOf(FlightActor.Props(cos, dr.flight, icao))); flightActors.Add(dr.flight, Context.ActorOf(FlightActor.Props())); flightActors[dr.flight].Tell(new FlightActor.FlightActorInit(cos, dr.flight, icao)); flightExpiry.Add(dr.flight, DateTime.Now); } // send message flightActors[dr.flight].Tell(req); // update timestamp flightExpiry[dr.flight] = DateTime.Now; } }); // clear out actors that haven't recently processed a message Receive <ExpireActors>(r => { // get idle processor list var toCleanup = flightExpiry .Where(z => z.Value.AddHours(1) < DateTime.Now) .Select(z => z.Key).ToList(); foreach (var t in toCleanup) { // shut down the actor var actor = flightActors[t]; actor.GracefulStop(TimeSpan.FromSeconds(10)); // clear out from lists flightActors.Remove(t); flightExpiry.Remove(t); } }); }