11use crate :: cross:: * ;
22use crate :: template:: mj_value:: * ;
3- use crate :: template:: neon:: NeonMiniJinjaContext ;
3+ use crate :: template:: neon:: * ;
44use crate :: utils:: bind_method;
55
66use log:: trace;
77use minijinja as mj;
88use neon:: prelude:: * ;
99use std:: cell:: RefCell ;
1010
11+ use crate :: template:: workers:: { JinjaEngineWorkerJob , JinjaEngineWorkerPool } ;
1112#[ cfg( feature = "python" ) ]
1213use pyo3:: { exceptions:: PyNotImplementedError , prelude:: * , types:: PyTuple , AsPyPointer } ;
1314
1415struct JinjaEngine {
1516 inner : mj:: Environment < ' static > ,
17+ workers_count : usize ,
18+ workers : Option < JinjaEngineWorkerPool > ,
1619}
1720
1821impl Finalize for JinjaEngine { }
@@ -123,14 +126,50 @@ impl JinjaEngine {
123126 }
124127 }
125128
126- Ok ( Self { inner : engine } )
129+ let workers_count = {
130+ let workers_count_float = options
131+ . get_value ( cx, "workers" ) ?
132+ . downcast_or_throw :: < JsNumber , _ > ( cx) ?
133+ . value ( cx) ;
134+
135+ if workers_count_float < 1_f64 {
136+ return cx. throw_error ( "Option workers must be a positive integer" ) ;
137+ }
138+
139+ match workers_count_float. to_string ( ) . parse :: < usize > ( ) {
140+ Ok ( v) => v,
141+ Err ( err) => {
142+ return cx. throw_error ( format ! ( "Option workers must be a positive: {}" , err) )
143+ }
144+ }
145+ } ;
146+
147+ Ok ( Self {
148+ inner : engine,
149+ workers_count,
150+ workers : None ,
151+ } )
127152 }
128153}
129154
130155type BoxedJinjaEngine = JsBox < RefCell < JinjaEngine > > ;
131156
132157impl JinjaEngine {
133- fn render_template ( mut cx : FunctionContext ) -> JsResult < JsString > {
158+ fn build_if_needed ( & mut self , cx : & mut FunctionContext ) -> & JinjaEngineWorkerPool {
159+ if let Some ( ref workers) = self . workers {
160+ return workers;
161+ }
162+
163+ self . workers = Some ( JinjaEngineWorkerPool :: new (
164+ self . workers_count ,
165+ cx. channel ( ) ,
166+ self . inner . clone ( ) ,
167+ ) ) ;
168+
169+ self . workers . as_ref ( ) . unwrap ( )
170+ }
171+
172+ fn render_template ( mut cx : FunctionContext ) -> JsResult < JsPromise > {
134173 #[ cfg( build = "debug" ) ]
135174 trace ! ( "JinjaEngine.render_template" ) ;
136175
@@ -142,16 +181,6 @@ impl JinjaEngine {
142181 let template_compile_context = CLRepr :: from_js_ref ( cx. argument :: < JsValue > ( 1 ) ?, & mut cx) ?;
143182 let template_python_context = CLRepr :: from_js_ref ( cx. argument :: < JsValue > ( 2 ) ?, & mut cx) ?;
144183
145- let engine = & this. borrow ( ) . inner ;
146- let template = match engine. get_template ( & template_name. value ( & mut cx) ) {
147- Ok ( t) => t,
148- Err ( err) => {
149- trace ! ( "jinja get template error: {:?}" , err) ;
150-
151- return cx. throw_from_mj_error ( err) ;
152- }
153- } ;
154-
155184 let mut to_jinja_ctx = CLReprObject :: new ( ) ;
156185 to_jinja_ctx. insert ( "COMPILE_CONTEXT" . to_string ( ) , template_compile_context) ;
157186
@@ -163,15 +192,20 @@ impl JinjaEngine {
163192 }
164193 }
165194
166- let compile_context = to_minijinja_value ( CLRepr :: Object ( to_jinja_ctx) ) ;
167- match template. render ( compile_context) {
168- Ok ( r) => Ok ( cx. string ( r) ) ,
169- Err ( err) => {
170- trace ! ( "jinja render template error: {:?}" , err) ;
195+ let ( deferred, promise) = cx. promise ( ) ;
171196
172- cx. throw_from_mj_error ( err)
173- }
174- }
197+ let mut this = this. borrow_mut ( ) ;
198+ let pool = this. build_if_needed ( & mut cx) ;
199+
200+ if let Err ( err) = pool. render ( JinjaEngineWorkerJob {
201+ template_name : template_name. value ( & mut cx) ,
202+ ctx : to_minijinja_value ( CLRepr :: Object ( to_jinja_ctx) ) ,
203+ deferred,
204+ } ) {
205+ return cx. throw_error ( format ! ( "Unable to render jinja template: {}" , err) ) ;
206+ } ;
207+
208+ Ok ( promise)
175209 }
176210
177211 fn load_template ( mut cx : FunctionContext ) -> JsResult < JsUndefined > {
@@ -185,13 +219,18 @@ impl JinjaEngine {
185219 let template_name = cx. argument :: < JsString > ( 0 ) ?;
186220 let template_content = cx. argument :: < JsString > ( 1 ) ?;
187221
188- if let Err ( err) = this. borrow_mut ( ) . inner . add_template_owned (
222+ let mut borrowed = this. borrow_mut ( ) ;
223+ if let Err ( err) = borrowed. inner . add_template_owned (
189224 template_name. value ( & mut cx) ,
190225 template_content. value ( & mut cx) ,
191226 ) {
192227 trace ! ( "jinja load error: {:?}" , err) ;
193-
194228 return cx. throw_from_mj_error ( err) ;
229+ } ;
230+
231+ if borrowed. workers . is_some ( ) {
232+ trace ! ( "Restart jinja workers" ) ;
233+ borrowed. workers = None ;
195234 }
196235
197236 Ok ( cx. undefined ( ) )
0 commit comments