Keats / tera

A template engine for Rust based on Jinja2/Django
http://keats.github.io/tera/
MIT License
3.47k stars 281 forks source link

Clone properties of `Tera` #529

Open zizhengtai opened 4 years ago

zizhengtai commented 4 years ago

I'm using Tera with actix-web, which creates a separate app state (including a Tera instance in my case) per thread. I was originally doing something like this:

// Compile the templates only once
let tera = Tera::new(...)?;

HttpServer::new(move || {
    App::new()
        .data(tera.clone())  // Cloning a `Tera` here
})

I looked into the struct Tera and realized that I'm actually cloning a bunch of stuff (such as HashMaps and Vecs), so I decided to do this instead:

let tera = Arc::new(Tera::new(...)?);

HttpServer::new(move || {
    App::new()
        .app_data(Data::from(Arc::clone(&tera)))  // Cloning an `Arc<Tera>` here
})

But then I noticed that there are already Arcs inside Tera, which I think is wasteful in this case. I could be totally wrong and maybe Tera is designed this way for a reason, but I think it'd be more flexible if we replace the Arcs inside Tera with Rcs. This will have several consequences:

This change will bring the following benefits:

The only downside I can think of is that making Tera not Send is a breaking change. I'd like to hear your opinions.

zizhengtai commented 4 years ago

Another way to do this while keeping backwards compatibility is:

struct TeraInner { / a bunch of stuff / }


However, I still think externalizing the `Arc` is the most flexible approach.
Keats commented 4 years ago

I do want tests/filters/functions to be Send though. Would https://github.com/getzola/zola/blob/master/components/templates/src/global_fns/mod.rs (+ rayon) still work without too much overhead?

zizhengtai commented 4 years ago

Would https://github.com/getzola/zola/blob/master/components/templates/src/global_fns/mod.rs (+ rayon) still work without too much overhead?

I'm not sure I follow...?