For general server architecture, see README.md
. This module implements the watchdog process.
Watchdog state #
Most LSP clients only send us file diffs, so to facilitate sending entire file contents to freshly restarted workers, the watchdog needs to maintain the current state of each file. It can also use this state to detect changes to the header and thus restart the corresponding worker, freeing its imports.
TODO(WN): We may eventually want to keep track of approximately (since this isn't knowable exactly) where in the file a worker crashed. Then on restart, we tell said worker to only parse up to that point and query the user about how to proceed (continue OR allow the user to fix the bug and then continue OR ..). Without this, if the crash is deterministic, users may be confused about why the server seemingly stopped working for a single file.
Watchdog <-> worker communication #
The watchdog process and its file worker processes communicate via LSP. If the necessity arises, we might add non-standard commands similarly based on JSON-RPC. Most requests and notifications are forwarded to the corresponding file worker process, with the exception of these notifications:
- textDocument/didOpen: Launch the file worker, create the associated watchdog state and launch a task to asynchronously receive LSP packets from the worker (e.g. request responses).
- textDocument/didChange: Update the local file state so that it can be resent to restarted workers.
Then forward the
didChange
notification. - textDocument/didClose: Signal a shutdown to the file worker and remove the associated watchdog state.
Moreover, we don't implement the full protocol at this level:
- Upon starting, the
initialize
request is forwarded to the worker, but it must not respond with its server capabilities. Consequently, the watchdog will not send aninitialized
notification to the worker. - After
initialize
, the watchdog sends the correspondingdidOpen
notification with the full current state of the file. No additionaldidOpen
notifications will be forwarded to the worker process. $/cancelRequest
notifications are forwarded to all file workers.- File workers are always terminated with an
exit
notification, without previously receiving ashutdown
request. Similarly, they never receive adidClose
notification.
Watchdog <-> client communication #
The watchdog itself should implement the LSP standard as closely as possible. However we reserve the right to add non-standard extensions in case they're needed, for example to communicate tactic state.
Events that worker-specific tasks signal to the main thread.
- terminated: Lean.Server.Watchdog.WorkerEvent
- importsChanged: Lean.Server.Watchdog.WorkerEvent
- crashed: IO.Error → Lean.Server.Watchdog.WorkerEvent
- ioError: IO.Error → Lean.Server.Watchdog.WorkerEvent
Instances For
- fileWorkerToClientForwarding: Lean.Server.Watchdog.CrashOrigin
- clientToFileWorkerForwarding: Lean.Server.Watchdog.CrashOrigin
Instances For
- crashed: Array Lean.JsonRpc.Message → Lean.Server.Watchdog.CrashOrigin → Lean.Server.Watchdog.WorkerState
The watchdog can detect a crashed file worker in two places: When trying to send a message to the file worker and when reading a request reply. In the latter case, the forwarding task terminates and delegates a
crashed
event to the main task. Then, in both cases, the file worker has its state set tocrashed
and requests that are in-flight are errored. Upon receiving the next packet for that file worker, the file worker is restarted and the packet is forwarded to it. If the crash was detected while writing a packet, we queue that packet until the next packet for the file worker arrives. - running: Lean.Server.Watchdog.WorkerState
Instances For
- doc : Lean.Server.DocumentMeta
- commTask : Task Lean.Server.Watchdog.WorkerEvent
- state : Lean.Server.Watchdog.WorkerState
- pendingRequestsRef : IO.Ref Lean.Server.Watchdog.PendingRequestMap
The pending requests map contains all requests that have been received from the LSP client, but were not answered yet. We need them for forwarding cancellation requests to the correct worker as well as cleanly aborting requests on worker crashes.
Instances For
Equations
- fw.stdin = IO.FS.Stream.ofHandle fw.proc.stdin
Instances For
Equations
- fw.stdout = IO.FS.Stream.ofHandle fw.proc.stdout
Instances For
Equations
- fw.erasePendingRequest id = ST.Ref.modify fw.pendingRequestsRef fun (pendingRequests : Lean.Server.Watchdog.PendingRequestMap) => Lean.RBMap.erase pendingRequests id
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- fw.queuedMsgs = match fw.state with | Lean.Server.Watchdog.WorkerState.running => #[] | Lean.Server.Watchdog.WorkerState.crashed queuedMsgs origin => queuedMsgs
Instances For
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Global import data for all open files managed by this watchdog.
- imports : Lean.Server.Watchdog.ImportMap
For every open file, the files that it imports.
- importedBy : Lean.Server.Watchdog.ImportMap
For every open file, the files that it is imported by.
Instances For
Updates d
with the new set of imports
for the file uri
.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Sets the imports of uri
in d
to the empty set.
Instances For
- sourceUri : Lean.Lsp.DocumentUri
- localID : Lean.JsonRpc.RequestID
Instances For
Equations
Instances For
- pendingServerRequests : Lean.Server.Watchdog.PendingServerRequestMap
- freshServerRequestID : Nat
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
- hIn : IO.FS.Stream
- hOut : IO.FS.Stream
- hLog : IO.FS.Stream
Command line arguments.
- fileWorkersRef : IO.Ref Lean.Server.Watchdog.FileWorkerMap
- initParams : Lean.Lsp.InitializeParams
We store these to pass them to workers.
- workerPath : System.FilePath
- srcSearchPath : System.SearchPath
- references : IO.Ref Lean.Server.References
- serverRequestData : IO.Ref Lean.Server.Watchdog.ServerRequestData
- importData : IO.Ref Lean.Server.Watchdog.ImportData
Instances For
Instances For
Instances For
Equations
- Lean.Server.Watchdog.findFileWorker? uri = do let __do_lift ← read let __do_lift ← ST.Ref.get __do_lift.fileWorkersRef pure (Lean.RBMap.find? __do_lift uri)
Instances For
Instances For
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Updates the global import data with the import closure provided by the file worker after it successfully processed its header.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Instances For
Instances For
Instances For
Tries to write a message, sets the state of the FileWorker to crashed
if it does not succeed
and restarts the file worker if the crashed
flag was already set. Just logs an error if
there is no FileWorker at this uri
.
Messages that couldn't be sent can be queued up via the queueFailedMessage flag and
will be discharged after the FileWorker is restarted.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Sends a notification to the file worker identified by uri
that its dependency staleDependency
is out-of-date.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Used in CallHierarchyItem.data?
to retain all the data needed to quickly re-identify the
call hierarchy item.
Instances For
Extracts the CallHierarchyItemData from item.data?
and returns none
if this is not possible.
Equations
- Lean.Server.Watchdog.CallHierarchyItemData.fromItem? item = do let __do_lift ← item.data? (Lean.fromJson? __do_lift).toOption
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
When a file is saved, notifies all file workers for files that depend on this file that this specific import is now stale so that the file worker can issue a diagnostic asking users to restart the file.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Lean.Server.Watchdog.handleDidClose p = Lean.Server.Watchdog.terminateFileWorker p.textDocument.uri
Instances For
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Instances For
Instances For
Instances For
Instances For
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
- workerEvent: Lean.Server.Watchdog.FileWorker → Lean.Server.Watchdog.WorkerEvent → Lean.Server.Watchdog.ServerEvent
- clientMsg: Lean.JsonRpc.Message → Lean.Server.Watchdog.ServerEvent
- clientError: IO.Error → Lean.Server.Watchdog.ServerEvent
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Starts loading .ileans present in the search path asynchronously in an IO task. This ensures that server startup is not blocked by loading the .ileans. In return, while the .ileans are being loaded, users will only get incomplete results in requests that need references.
Equations
- One or more equations did not get rendered due to their size.