Skip to content

Commit 9c9647d

Browse files
committed
web: speed up loading Tera templates
1 parent e7ee68b commit 9c9647d

File tree

3 files changed

+51
-9
lines changed

3 files changed

+51
-9
lines changed

Cargo.lock

+4-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+6-5
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ staticfile = { version = "0.4", features = [ "cache" ] }
5757
tempfile = "3.1.0"
5858

5959
# Templating
60-
tera = { version = "1.3.0", features = ["builtins"] }
60+
tera = { version = "1.3.1", features = ["builtins"] }
61+
walkdir = "2"
6162

6263
# Template hot-reloading
6364
arc-swap = "0.4.6"
@@ -67,17 +68,17 @@ notify = "4.0.15"
6768
chrono = { version = "0.4.11", features = ["serde"] }
6869
time = "0.1" # TODO: Remove once `iron` is removed
6970

71+
[dependencies.postgres]
72+
version = "0.15"
73+
features = ["with-chrono", "with-serde_json"]
74+
7075
[target.'cfg(not(windows))'.dependencies]
7176
# Process information
7277
procfs = "0.7"
7378

7479
[target.'cfg(windows)'.dependencies]
7580
path-slash = "0.1.1"
7681

77-
[dependencies.postgres]
78-
version = "0.15"
79-
features = ["with-chrono", "with-serde_json"]
80-
8182
[dev-dependencies]
8283
once_cell = "1.2.0"
8384
criterion = "0.3"

src/web/page/templates.rs

+41-1
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@ use crate::db::Pool;
22
use crate::error::Result;
33
use arc_swap::ArcSwap;
44
use chrono::{DateTime, Utc};
5+
use failure::ResultExt;
56
use notify::{watcher, RecursiveMode, Watcher};
67
use postgres::Connection;
78
use serde_json::Value;
89
use std::collections::HashMap;
10+
use std::path::PathBuf;
911
use std::sync::{mpsc::channel, Arc};
1012
use std::thread;
1113
use std::time::Duration;
1214
use tera::{Result as TeraResult, Tera};
15+
use walkdir::WalkDir;
16+
17+
const TEMPLATES_DIRECTORY: &str = "tera-templates";
1318

1419
/// Holds all data relevant to templating
1520
#[derive(Debug)]
@@ -84,7 +89,16 @@ fn load_rustc_resource_suffix(conn: &Connection) -> Result<String> {
8489
}
8590

8691
pub(super) fn load_templates(conn: &Connection) -> Result<Tera> {
87-
let mut tera = Tera::new("tera-templates/**/*")?;
92+
// This uses a custom function to find the templates in the filesystem instead of Tera's
93+
// builtin way (passing a glob expression to Tera::new), speeding up the startup of the
94+
// application and running the tests.
95+
//
96+
// The problem with Tera's template loading code is, it walks all the files in the current
97+
// directory and matches them against the provided glob expression. Unfortunately this means
98+
// Tera will walk all the rustwide workspaces, the git repository and a bunch of other
99+
// unrelated data, slowing down the search a lot.
100+
let mut tera = Tera::default();
101+
tera.add_template_files(find_templates_in_filesystem(TEMPLATES_DIRECTORY)?)?;
88102

89103
// This function will return any global alert, if present.
90104
ReturnValue::add_function_to(
@@ -120,6 +134,32 @@ pub(super) fn load_templates(conn: &Connection) -> Result<Tera> {
120134
Ok(tera)
121135
}
122136

137+
fn find_templates_in_filesystem(base: &str) -> Result<Vec<(PathBuf, Option<String>)>> {
138+
let root = std::fs::canonicalize(base)?;
139+
140+
let mut files = Vec::new();
141+
for entry in WalkDir::new(&root) {
142+
let entry = entry?;
143+
let path = entry.path();
144+
145+
if !entry.metadata()?.is_file() {
146+
continue;
147+
}
148+
149+
// Strip the root directory from the path and use it as the template name.
150+
let name = path
151+
.strip_prefix(&root)
152+
.with_context(|_| format!("{} is not a child of {}", path.display(), root.display()))?
153+
.to_str()
154+
.ok_or_else(|| failure::format_err!("path {} is not UTF-8", path.display()))?
155+
.to_string();
156+
157+
files.push((path.to_path_buf(), Some(name)));
158+
}
159+
160+
Ok(files)
161+
}
162+
123163
/// Simple function that returns the pre-defined value.
124164
struct ReturnValue {
125165
name: &'static str,

0 commit comments

Comments
 (0)