]>
Commit | Line | Data |
---|---|---|
f035d41b XL |
1 | # On-Demand (Lazy) Inputs |
2 | ||
3 | Salsa input queries work best if you can easily provide all of the inputs upfront. | |
4 | However sometimes the set of inputs is not known beforehand. | |
5 | ||
6 | A typical example is reading files from disk. | |
7 | While it is possible to eagerly scan a particular directory and create an in-memory file tree in a salsa input query, a more straight-forward approach is to read the files lazily. | |
8 | That is, when someone requests the text of a file for the first time: | |
9 | ||
10 | 1. Read the file from disk and cache it. | |
11 | 2. Setup a file-system watcher for this path. | |
12 | 3. Invalidate the cached file once the watcher sends a change notification. | |
13 | ||
14 | This is possible to achieve in salsa, using a derived query and `report_synthetic_read` and `invalidate` queries. | |
15 | The setup looks roughly like this: | |
16 | ||
17 | ```rust,ignore | |
18 | #[salsa::query_group(VfsDatabaseStorage)] | |
19 | trait VfsDatabase: salsa::Database + FileWatcher { | |
20 | fn read(&self, path: PathBuf) -> String; | |
21 | } | |
22 | ||
23 | trait FileWatcher { | |
24 | fn watch(&self, path: &Path); | |
25 | fn did_change_file(&mut self, path: &Path); | |
26 | } | |
27 | ||
3dfed10e | 28 | fn read(db: &dyn salsa::Database, path: PathBuf) -> String { |
f035d41b XL |
29 | db.salsa_runtime() |
30 | .report_synthetic_read(salsa::Durability::LOW); | |
31 | db.watch(&path); | |
32 | std::fs::read_to_string(&path).unwrap_or_default() | |
33 | } | |
34 | ||
35 | #[salsa::database(VfsDatabaseStorage)] | |
36 | struct MyDatabase { ... } | |
37 | ||
38 | impl FileWatcher for MyDatabase { | |
39 | fn watch(&self, path: &Path) { ... } | |
40 | fn did_change_file(&mut self, path: &Path) { | |
41 | self.query_mut(ReadQuery).invalidate(path); | |
42 | } | |
43 | } | |
44 | ``` | |
45 | ||
46 | * We declare the query as a derived query (which is the default). | |
47 | * In the query implementation, we don't call any other query and just directly read file from disk. | |
48 | * Because the query doesn't read any inputs, it will be assigned a `HIGH` durability by default, which we override with `report_synthetic_read`. | |
49 | * The result of the query is cached, and we must call `invalidate` to clear this cache. |