lg-sim source code review (2019.09)

the recent version of lg-sim 2019.09 has additionally support for webUI, cloud, which is a big enhencement. the following code review is focusing on new components to support WebUI, cluster management.

database

database used sqlite project, which is an embedded in-memory db; the ORM used PetaPoco project; there are a few db related serices, e.g. vehicleService, simulationService, which will be used in RESTful web request.

  • DatabaseManager:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
static IDatabaseBuildConfiguration DbConfig ;
Init(){
DbConfig = GetConfig(connectionString)
using db = new SqliteConnection(connectionString){
db.Open()
}
CreateDefaultDbAssets(){
using db = Open()
if (info.DownloadEnvs != null){
map = new MapModel(){url = url LocalPath=localPath;}
id = db.Insert(map)
}
if (info.DownloadVehicles != null){}
if(defaultMap.HasValue)
{
sim1 = new SimulationModel(){ Cluster=0, Map=defaultMap.Value, ApiOnly=false};
AddSimulation(db, sim1, noBridgeVehicle);
AddSimulation(db, sim, apolloVehicle);
db.Insert(simx)
}
}
AddSimulation(IDatabase db, sim,vehicle){
conn = new ConnectionModel(){
simulation = id,
vehicle = vehicle.Value,
}
db.Insert(conn)
}
AddVehicle(db, sim,vehicle){
conn = new VehicleModel(){
Url = url ,
}
db.Insert(vehicle)
return vehicle.Id;
}
PendingVehicleDownloads(){
using db=Open(){
var sql = Sql.Builder.From("vehicles").Where("status=00", "Downloading");
return db.Query<VehicleModel>(sql);
}
}

database ORMs

using PetaPoco to define ORM models, such as
users, sessions, maps, vehicles, clusters, simulations

PetaPoco

a few operators in PetaPoco, such as Page, used to query a page; Single, used to query a single item; Insert; Delete; Update

database provider

1
2
3
SQLiteDatabaseProvider =>
GetFactory("Mono.Data.Sqlite.SqliteFactory, Mono.Data.Sqlit")

called inside DatabaseManager::Init().

database services

  • VehicleService : IVehicleService

  • MapService

  • NotificationService => NotificationManager.SendNotification()

  • DownloadService => DownloadManager.AddDownloadToQueue()

  • ClusterService

  • SessionService

  • SimulationService

Web model

web model is where WebUI server located, which is served by Nancy project, in which a new design metholody is applied: Inversin of Control Contaner(IoC), namely 控制反转 in chinese. IoC is used to inject implementation of class, and manage lifecycle, dependencies.

web model is the server where talk to webUI through routes, which is defined in the React project.

Nancy

used to build HTTP based web service,

  • FileStream
  • StreamResponse
  • TinyIoC
  • UnityBootstrapper : DefaultNancyBootstrapper, used to automatic discovery of modules, custm model binders, dependencies.
  • /Assets/Scripts/Web/Nancy/NancyUnityUtils
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ConfigureApplicatinContainer(TinyIoCContainer container)
{
container.Register<UserMapper>();
container.Register<IMapService>();
container.Register<IClusterService>();
container.Register<IVehicleService>();
container.Register<ISimulationService>();
}
```
### route modules
```c#
SimulationModule : NancyModule()
{
class SimulationRequest{}
class SimulationResponse{}
Get("/", x={})
Post("/", x={})
Put("/{id:long}", x={})
Post("/{id:long}/start", x={})
Post("/{id:long}/stop", x={})
}

inside some of the route modules will do query or update the sqlite database for special objects. till here is the complete web back-end server, with a http server and an in-memory database.

the webUI frontend is based on React, about React check a previous blog. in the React WebUI project will have http requests corresponding to each of routes defined here.

React front end is very independent framework, which should be handled by an independent team in standard pipeline.

Config & Loader

  • /Assets/Scripts/Web/Config.cs:

used to define WebHost, WebPort, ApiHost, ClourUrl, Headless, Sensors, Bridges e.t.c

  • Loader.cs :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Loader Instance ; //Loader object is never destroyed, even between scene reloads
Loader.Start(){
DatabaseManager.Init();
var config = new HostConfguration{} ; // ?
Server = new NancyHost(Config.WebHost);
Server.Start();
DownloadManager.Init();
}
Loader.StartAsync(simulation){
Instance.Actions.Enqueue() =>
var db = DatabaseManager.Open()
AssetBundle mapBundle = null;
simulation.Status "Starting"
NotificationManager.SendNotification();
Instance.LoaderUI.SetLoaderUIState();
Instance.SimConfig = new SimlationConfig(){
Clusters, ApiOnly, Headless, Interative, TimeOfDay, UseTraffic...
}
}
Loader.SetupScene(simulation){
var db = DatabaseManager.Open()
foreach var agentConfig in Instance.SimConfig.Agents:
var bundlePath = agentConfig.AssetBundle
var vehicleBundle = AssetBundle.LoadfromFile(bundlePath)
var vehicleAssets = vehicleBundle.GetAllAssetNames();
agentConfig.Prefab = vehicleBundle.LoadAsset<GO>(vehicleAssets[0])
var sim = CreateSimulationManager();
Instance.CurrentSimulation = simulation
}
  • DownloadManager

class Download();
Init(){ client = new WebClient();  ManageDownloads(); }

network module

network module is used for communication among master and clients(workers) in the cluster network for cloud support. the P2P network is built on LiteNetLib which is a reliable UDP lib.

LiteNetLib

LiteNetLibis Udp package, used to P2P communication among master node and slave nodes here, where are defined as MasterManager, ClientManager.

usage of LiteNetLib can be found in the wiki-usage)