on master help sign in
Doc: add FAQ entry on `ob run`
commit667e15ed24c66eea853192e94e17cf20f309f7a0 authorSebastien Mondet <seb@mondet.org> dateFri 12 Apr 2019, 14:39 (8 years ago) parent20ba787
1 file changed+60−1
FAQ.md+60−1
FAQ.md+60−1
@@ -3,7 +3,7 @@
331. [How do I fix invalid entitlements? ](#how-do-i-fix-invalid-entitlements)
441. [`ob thunk update` or `ob deploy update` fails](#ob-thunk-update-or-ob-deploy-update-fails)
551. [How do I fix `Ambiguous module name` errors?](#how-do-i-fix-ambiguous-module-name-errors)
6−
6+1. [What does `ob run` actually do?](#what-does-ob-run-actually-do)
77
88### How do I fix invalid entitlements?
99
@@ -59,3 +59,62 @@ error:
5959```
6060then specify the package you want in the import, e.g:
6161`import "cryptonite" Crypto.Hash`
62+
63+
64+### What does `ob run` actually do?
65+
66+
67+#### Short version:
68+
69+`ob run` starts a [`ndmitchell/ghcid`](https://github.com/ndmitchell/ghcid)
70+process, within a carefully crafted `nix-shell`, which tries to build your
71+project and,
72+
73+* either displays compilation errors,
74+* or starts the Obelisk server, which serves:
75+ * your backend's route handlers,
76+ * the static assets,
77+ * the result of compiling & linking your frontend with GHCJS.
78+
79+#### Longer version:
80+
81+Assuming we are in a project created with `ob init`, `ob run` calls (see
82+`./lib/command/src/Obelisk/Command.hs`):
83+
84+ nix-shell -A shells.ghc --run 'ob --no-handoff internal run-static-io <real-run-function>'
85+
86+where
87+
88+* `shells.ghc` is defined in `./default.nix` by importing `./.obelisk/impl/default.nix` which
89+ is `./default.nix` in the present (Obelisk) repository,
90+* `run-static-io` is a logging-enabled command wrapper
91+ (cf. `runObelisk` in `./lib/command/src/Obelisk/App.hs`).
92+
93+In this case, it runs the function `Obelisk.Command.Command.run` (defined in
94+`./lib/command/src/Obelisk/Command/Run.hs`).
95+
96+* It creates a GHCid config from a Nix expression:
97+ * which loads 3 packages: "backend", "common", "frontend", and
98+ * obtains a free port number.
99+* Then runs `ghcid`
100+ * with a `--test` command that reruns `Obelisk.Run.run` at each restart.
101+
102+It is defined in `./obelisk/lib/run/src/Obelisk/Run.hs`:
103+
104+* It creates a thread (`forkIO`) which starts the main backend.
105+ This runs `runSnapWithCommandLineArgs` and
106+ * passes routes to the backend
107+ (result of the `_backend_run` field of the `Backend x y` “user” record)
108+ * or to `serveDefaultObeliskApp` (`./lib/backend/src/Obelisk/Backend.hs`) to serve
109+ static assets (incl. the GHCJS output of the frontend).
110+* Starts `runWidget`
111+ which itself runs
112+ [runSettingsSocket](https://hoogle.haskell.org/?hoogle=runSettingsSocket)
113+ (the *“TCP listen loop”*):
114+ * it binds to TCP socket, and
115+ * creates the HTTP connection manager
116+ ( [`newManager`](https://hackage.haskell.org/package/http-client-0.6.3/docs/Network-HTTP-Client.html#v:newManager))
117+ * calls `obeliskApp` which
118+ * has a route to serve [`ghcjs/jsaddle`](https://github.com/ghcjs/jsaddle) (GHCJS bindings to JS/Dom),
119+ * runs the frontend (*on* the server), to produce pre-rendered pages,
120+ * falls back to proxying the backend (`fallbackProxy`)