107 lines
7.6 KiB
Plaintext
107 lines
7.6 KiB
Plaintext
In SPARC, the app menu is created from app/assets/json/global/app-menu-map.json
|
|
Each entry defines a route.
|
|
A "high level" route is then configured in app/config/baseRoutes.json that delegates a group of URLs to a controller.
|
|
Then, a controller, in its associated .json file defines in its "routes" section the sub-route managed by the controller,
|
|
and the method to be called inside that controller.
|
|
|
|
In SPARC, models inherit from the core and from WindozModel a mecanism that gets the URL from app/assets/json/global/services.json
|
|
That configuration file associates actions grouped in sections to API urls and http method.
|
|
Sections are identified by an URL-prefix (only used as label), and correspond to API "services".
|
|
The server-side of this API is served by the node daemon in p42api.
|
|
p42api has a folder 'api' with one file / module per API service, they are all declared in and imported by api/index.js.
|
|
Each module defines a mapping object, that contains all the complete urls served, http-method, and local handling method.
|
|
|
|
We are now focusing on P42 God Daemons (in folder p42GodDaemons).
|
|
Every daemon in there is connected to several Redis. At least one Arena redis, and one System Redis.
|
|
PUB/SUB channels are prefixed accordingly, following the configuration token "chansNamespace"
|
|
and anything outside the configured combination Redis host & port + chansNamespace is illegal.
|
|
In the future, there might be several different Redis (in mesh) serving the same chansNamespace.
|
|
|
|
GPS Daemon is the global positionning system of the arena.
|
|
It holds the current position of every agent in the arena.
|
|
Agents change their 3D speed vector whenever they want by informing GPS (via the agentVectorChangeChannel)
|
|
A typical agent event looks like
|
|
{ "eventType": "change", "payload": { "newVector": { "x": 5, "y": -2.34, "z": 0 } }, "sender": "agent42" }
|
|
On every speed vector change, GPS computes the 4D worldline of the agent,
|
|
and scans all other worldlines to find those intersecting, or approaching less than a configurable distance.
|
|
Each collision/ near-miss is then registered.
|
|
As time passes, GPS fires events towards concerned agents based on this register.
|
|
On every speed vector change, this register is searched and all entries containing the agent changing its speed are deleted.
|
|
To speed-up and limit the intersection computations, we will take an approach using rectangular 4-prisms :
|
|
Each pair of wordlines to test for collision / near-miss is enclosed in a 4-prism of a certain configurable time-height (thus how far in the future we test),
|
|
and we just test for intersecting prisms.
|
|
Only if the prisms intersect do we compute the real minimal-distance and its time, that we keep in the register.
|
|
Comparing a pair of worldlines should be a separated method and the looping through all agents in a separated method as well.
|
|
The reason for this remark is to take provision for a future where I might want to paralellize this (instead of looping through), in a GPU.
|
|
|
|
|
|
|
|
We need to think about how we start a new simulation from GPS point of view :
|
|
As we are in a distributed context, here is the workflow I'm thinking of :
|
|
1. Some orchestrator process will put all agents data in the arena Redis store.
|
|
2. Then it will start all agents processes, in a special mode "onYourMarks" where they can initialize, time is frozen to zero, any non initialization computation is forbidden.
|
|
3. When each agent is initialized, it fires an arena event "readyToStart"
|
|
4. When the orchestrator has accounted for all agents, it fires an "arenaStart" event, that unleashes all agents.
|
|
|
|
Now where is GPS in all of this :
|
|
GPS should behave like an agent: listen for "onYourMarks" event, initialize, send "readToStart" when done, and start time-ticking when it received a "bigBang" event.
|
|
Contrary to agents, GPS daemon itself is supposed to be running already.
|
|
So the initialization is mainly doing a first agents scan to fill its registry. (with an unvalued T0 and collision-ticks not running). Scanning all agents means going into redis store to get their vector (its only after this step than GPS become the positions authority)
|
|
Upon receiving "bigBang", T0 is valued, and the collisionsTicks starts.
|
|
That's the general idea.
|
|
Please check if you don't see incoherence, gap or edge case.
|
|
|
|
|
|
|
|
5. GPS time communicated to agents is simulation time, thus with T(bigBang) = 0
|
|
Therefore, when the orchestrator send a "bigBang" event, GPS starts general scan
|
|
and does the pre-compute with all positions at T=0
|
|
For eventual time-elapsed computations internal to GPS, it can keep a reference, say bigBangEpoch to epoch (miliseconds)
|
|
at the moment he receives the "bigBang" event.
|
|
From then on, current Simulation time is now() - bigBangEpoch
|
|
|
|
|
|
Next step: the embrio of simOrchestrator.
|
|
Can you create a second GodDaemon called like that, aside GPS, that uses the same config, the same general pattern, adapted start & stop scripts,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
So, the first thing you must understand, is that all busses, thus all meshes and all redisConnexions can carry both types of messages :
|
|
1. Request-reply: action request (possibly with reqid) requestor to provider. After action completion (or rejection), the provider answers the requestor (private chan replacing {uuid} with sender) with a reply (on the same reqid if present).
|
|
The payload must contain "action", with an imperative form.
|
|
Action must be verified to arrive on a specific chan, and the sender be allowed by access-rights.
|
|
|
|
2. Events broadcasting: not a request, just a message for anybody interested (so no "rejection" per se, but eventual ignore). No answer, but eventual local processing which might or not endup firing other event(s).
|
|
The payload must contain "eventType", with a generally a past tense. (like "he guys, I UPDATED my color")
|
|
Event routing combines chan & eventType (for example, and "updated" eventType could appear on a agentColor chan, and on a agentHealth chan, with different meanings and thus handling)
|
|
|
|
These two types can happen anywhere, it is not a "per mesh drift".
|
|
Probably, most Actions will concentrate in the SYSTEM mesh, because the management by the front-end and API is mostly user driven (user action becomes a request on the system bus).
|
|
Probably, the ARENA will be mostly event-driven, because agents have no overview of the arena (so to who ask for what?)
|
|
|
|
Nevertheless, there will be many cases where this is not true:
|
|
GODs emitting events that other gods or even the Front-End should be aware of.
|
|
The observer feeding the GUI on arena changes in an event-driven way.
|
|
Agent in the Arena requesting a service from a known god. (like "Hey GPS, give me my latest vector")
|
|
And maybe even someday clever agents that provide actions to other agents in their proximity for example.
|
|
|
|
"Action" folder was originally meant for...actions !
|
|
|
|
Now we need to find a clean, elegant, universal (across daemons & across meshes)
|
|
way of coexist both actions and events.
|
|
|
|
Describe a proposal that stays close to what we have, but separates events from actions.
|
|
|
|
We have another issue: If I'm not mistaken, a front-end "sender" UID is actually his login UID.
|
|
That means that a user opening 2 browsers is viewed as the same sender on both.
|
|
Therefore, using sender as upsert key in the subscriptions registry of observer is problematic,
|
|
because we should allow the same user to view different things on different browsers.
|
|
Maybe in the second browser he's viewing another angle, or meybe he's not viewing this particular sim at all.
|
|
|
|
Back to business.
|
|
I slightly changed the listSims query, so we can display sim name, primordial frame name and owner name.
|
|
|
|
Now that this mecanism is in place in the gateway, Let's change Observer so that it uses a combination of sender and cnxId as key for its frustum register, instead of just sender |