Closed peddermaster2 closed 1 year ago
By design Engine
is read-only. There is no way to obtain a mutable reference to the inner engine
This choice was made to maximise performance. If the engine were wrapped inside a Mutex
, we could archive interior mutability, but this would result on lower server throughput. Nonetheless, here are some alternatives:
TemplateEngine
yourself following examples/custom_engine.rs
. Keep in mind the limitations imposed by IntoResponse
(no async support) and the performance hit.///! Not tested
use std::sync::{Mutex, Arc};
struct MutableEngine(pub Arc<Mutex<Tera>>);
impl MutableEngine {
pub fn reload(&self) -> tera::Result<()>{
self.lock().unwrap().full_reload()
}
}
impl TemplateEngine for MutableEngine {
type Error = axum_template::engine::TeraError;
fn render<S: Serialize>(&self, key: &str, data: S) -> Result<String, Self::Error> {
let tera = self.0.lock().unwrap();
let data = Context::from_serialize(data)?;
let rendered = tera.render(key, &data)?;
Ok(rendered)
}
}
///! Not tested
type AppEngine = Engine<Tera>;
#[derive(Clone, FromRef)]
struct AppState {
engine: AppEngine,
}
#[tokio::main]
async fn main() {
loop {
let tera = Tera::new("templates/**.html").expect("Template folder not found");
let app = Router::new()
.with_state(AppState {
engine: Engine::from(tera),
});
println!("See example: http://127.0.0.1:8080/example");
Server::bind(&([127, 0, 0, 1], 8080).into())
.serve(app.into_make_service())
.with_graceful_shutdown(async { /* Watch for file changes */ })
.await
.unwrap();
}
}
My use case is to listen on changes in the template directory and reload the templates (with
Tera::full_reload()
).I'm not sure how to provide the required
&mut Tera
though.