Wait for the module host to become available, retrying with backoff. This is useful for routes like `/schema` that may be called while the database is still loading. Instead of returning an immediate 500, we poll for up to `timeout` before giving up.
(&self, timeout: std::time::Duration)
| 113 | /// database is still loading. Instead of returning an immediate 500, we |
| 114 | /// poll for up to `timeout` before giving up. |
| 115 | pub async fn wait_for_module(&self, timeout: std::time::Duration) -> Result<ModuleHost, NoSuchModule> { |
| 116 | let deadline = tokio::time::Instant::now() + timeout; |
| 117 | let mut interval = tokio::time::Duration::from_millis(100); |
| 118 | loop { |
| 119 | match self.host_controller.get_module_host(self.replica_id).await { |
| 120 | Ok(module) => return Ok(module), |
| 121 | Err(NoSuchModule) => { |
| 122 | if tokio::time::Instant::now() >= deadline { |
| 123 | return Err(NoSuchModule); |
| 124 | } |
| 125 | tokio::time::sleep(interval).await; |
| 126 | // Exponential backoff: 100ms, 200ms, 400ms, 800ms, 1s, 1s, ... |
| 127 | interval = (interval * 2).min(tokio::time::Duration::from_secs(1)); |
| 128 | } |
| 129 | } |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | pub async fn module_watcher(&self) -> Result<watch::Receiver<ModuleHost>, NoSuchModule> { |
| 134 | self.host_controller.watch_module_host(self.replica_id).await |
no test coverage detected