DB/Device Supervision
DB Supervisor
DB Supervisor wraps every DB in Queue, Writer, Dry Status Relay, Decider and Compactor.
Queue and Writer are described in DB Prioritization.
Dry Status Relay is Agent that holds read-only state of DB. It is updated by Decider. And read by UI to show red indication.
Decider checks space left on device and starts writing or read-only configuration under WriteSupervisor. For write it starts Writer and Compactor. For read-only - DryWriter, which does no writes in DB or filesystem.
Compactor awaits for period of inactivity (7 minutes) and starts DB compaction. When Writer has something to write, it lets Compactor know, so compaction will get canceled if unfinished.
The supervision strategy is rest for one. Which means that all peers to the right will get restated if children failed. I.e. if CubDB fails, Dry Status Relay, WriteSupervisor and Decider get restarted as well. Queue continues to work, aggregating all the changes User generated. This provides seamless switching into Read Only mode when there is no room to write data.
graph TD;
s(DB Supervisor)
s --> Queue
s --> db[(CubDB)]
s --> ds[Dry Status Relay]
s --> ws{{WriteSupervisor}}
s --> Decider
ws --> Compactor
ws --> Writer
ws -.-> DryWriter
This approach used in all DB Supervisors. Each handles its own DB, otherwise they are identical
-
Chat.Db.InternalDbSupervisor -
Chat.Db.MainDbSupervisor -
Chat.Db.MediaDbSupervisor
Device Supervision
Device managing happens in Platform project. (It incorporates Chat as dependency)
Here is a simplified supervision tree.
graph LR;
subgraph Chat
ids(InternalDbSupervisor)
mds(MainDbSupervisor)
meds(MediaDbSupervisor)
ca(Application)
ca -.-> ids
end
pa(Application)
ds(DeviceSupervisor)
cb[ChatBridge]
di[DriveIndication]
drive_sup{{Drives}}
dr[Drives.Registry]
udd[UsbDrives.Detector]
pa --> cb
pa --> di
pa --> ds
ds --> drive_sup
ds --> dr
ds --> udd
drive_sup -..-> mds
drive_sup -..-> meds
DriveIndication handles extra LED indication hardware
ChatBridge lets Chat to talk to Platform. Wifi setting and drives interaction are possible here.
UsbDrives.Detector polls filesystem for USB devices plug/unplug.
Drives.Registry registers processes used in drive dedicated subtrees.
Drives - supervises detected drives. We need Dynamic Supervisors to start or shutdown supervision subtrees, since devices are not always present. Each drive gets its own subtree.
Drive subtree consists of 2 parts.
- Booting - heals filesystem, mounts it and decideces which scenario to run
- Scenario - supervises given scenario behavior
Depending on scenario, subtree will include MainDbSupervisor or MediaSupervisor to supervise DB.
graph TD;
ds{{Drives}}
bs(Boot)
dis[DriveIndicationStarter]
h[[Healer]]
healed{{Healed}}
m[[Mounter]]
mounted{{Mounted}}
sc{{Scenario}}
d[Decider]
ds -.-> bs
bs --> dis
bs --> healed
bs --> h
healed --> m
healed --> mounted
mounted --> sc
mounted --> d
DriveIndicationStarter starts indication on custom hardware and ands it when drive ejected (i.e. this process terminated)
Healer detects FS used on drive and checks FS w/ coresponding tool (FAT, exFAT or F2FS)
Mounter mounts device into device dedicated folder
Decider checks device content and starts according scenario under Scenario supervisor.
Main drive supervision
graph TD;
pmds(Platform MainDbSupervisor)
mts(Task.Supervisor)
mm[[Mounter]]
mdt[DirTask]
mds(Chat MainDbSupervisor)
mb[[Bouncer]]
ms[[Starter]]
mc[[Copier]]
mr[[Replicator]]
msw[[Switcher]]
pmds --> mts
pmds --> mm
pmds --> mdt
pmds --> mds
pmds --> mb
pmds --> ms
pmds --> mc
pmds --> mr
pmds --> msw
Mounter mounts device into folder specified. And unmounts when terminated.
DirTask ensures that device filesystem has the folder to hold DB.
Chat MainDbSupervisor is DB Supervisor from Chat application described above.
Bouncer prevents DB directory from being renamed.
Starter changes global DB status (in application config). And reverts it back when terminated.
Copier starts blinking leds and copies data. And finishing blinking when terminated.
Replicator starts sync to internal DB every 5 mins. And stops when terminated.
Switcher switches Current DB to main. And reverts Current DB back to internal when terminated.
Media drive supervision
graph TD;
pms(MediaSupervisor)
mets(Task.Supervisor)
mem[[Mounter]]
fds[FunctionalityDynamicSupervisor]
d[MediaDecider]
pms --> mets
pms --> mem
pms --> fds
pms --> d
pbds(Platform BackupDbSupervisor)
pcss(Platform CargoSyncSupervisor)
poss(Platform OnlinersSyncSupervisor)
fds ---> pbds
fds ---> pcss
fds ---> poss
bdt[DirTask]
bmds(Chat MediaDbSupervisor)
bb[[Bouncer]]
bs[[Starter]]
bc[[Copier]]
bst[[Stopper]]
pbds --> bdt
pbds --> bmds
pbds --> bb
pbds --> bs
pbds --> bc
pbds --> bst
csdt[DirTask]
csmds(Chat MediaDbSupervisor)
csb[[Bouncer]]
css[[Starter]]
cscds[[CargoDynamicSupervisor]]
csl[[Logic]]
csc[[Copier]]
csst[[Stopper]]
pcss --> csdt
pcss --> csmds
pcss --> csb
pcss --> css
pcss --> cscds
pcss --> csl
cscds --> csc
cscds --> csst
osdt[DirTask]
osmds(Chat MediaDbSupervisor)
osb[[Bouncer]]
oss[[Starter]]
osods[[OnlinersDynamicSupervisor]]
osl[[Logic]]
osc[[Copier]]
osst[[Stopper]]
poss --> osdt
poss --> osmds
poss --> osb
poss --> oss
poss --> osods
poss --> osl
osods --> osc
osods --> osst
Mounter mounts device into folder specified. And unmounts when terminated.
Decider figures out which functionality to start under FunctionalityDynamicSupervisor.
It does it by checking whether device contains appropriate directory (backup_db for backup, cargo_db for cargo, or onliners_db for onliners sync).
If not, it checks the media settings in the Chat Admin room.
If it’s not set yet, the default functionality is used (backup).
Some of the modules are reused between the functionalities. We’ll describe them here while the unique aspects of the functionalities will be described in the below sections.
DirTask ensures that device filesystem has the folder to hold DB.
Chat MediaDbSupervisor is DB Supervisor from Chat application described above.
Bouncer prevents DB directory from being renamed.
Starter changes global DB status (in application config). And reverts it back when terminated.
Copier starts blinking leds and copies data. And finishing blinking when terminated.
Stopper starts extra LED blinking and makes Platform MediaSupervisor to stop. On termination stops LED blinking.
Platform BackupDbSupervisor
Synchronizes MainDb and BackupDb by copying the data that’s available on the device, but not in the MainDb and vice versa.
Platform CargoDbSupervisor
Copies data from the Cargo room. If there’s some data on the device, it copies it to the main drive. Otherwise, it copies data from the only room on main drive. If the room doesn’t exist yet, or if there are multiple rooms, it skips copying data.
Logic is responsible for deciding which room is for Cargo, then starts Copier and Stopper under
CargoDynamicSupervisor.
Platform OnlinersSyncSupervisor
Backs data up for the online users. If there’s some data data on the device, it restores it, but again only for the online users. Accomplishes this by sending a request for the keys to each online users’ LiveView process. After receiving keys for all online users and their rooms, it gathers the content on the device belonging to them and copies it from the device, then gathers the content in the MainDb and copies it to the device.
Logic is responsible for sending and receiving PubSub requests, getting the keys for
the content that needs to be copied both from and to BackupDb, and starting
Copier and Stopper under OnlinersDynamicSupervisor.