<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[thought to share about hosting jsreport in azure app service and questions about async rendering]]></title><description><![CDATA[<p>I'm working on a project that needs to:<br />
move on-prem jsreport instance to azure app service<br />
add template change tracking, in my repository devs can run jsreport that using /[myTempalteStore] as template-store locally</p>
<p>I chose git for template change tracking and here are the issues I got so far and what I did to resolve / found workaround. hope it helps :D</p>
<ol>
<li>
<p>Jsreport docker instance did not respond to warm-up call,<br />
This happens when you scale-out. Every new instance will end up in this.<br />
Restart the instance will work but I don't like restarting each new instance during scale-out<br />
The root cause is when the app service tries to run the docker instance it tries to listen to port 80, ignoring the docker file's specification of 5488<br />
You configure appservice to listen to 5488 instead, using config WEBSITES_PORT</p>
</li>
<li>
<p>template-store issues:<br />
since it's scaled I don't want call api for template deployment for each instance, i need a shared source of truth.</p>
</li>
</ol>
<p>2.1 I first tried azure file share as template store according to the instruction from jsreport home page.<br />
template deployment is done by<br />
-&gt; 2.1.1 azcopying the files from git to azure file share when a commit is pushed<br />
-&gt; 2.2.2 then restart staging-slot<br />
-&gt; 2.3.3 then swap</p>
<p>I don't need 2.1.2 and 2.1.3 if I turn on the external change sync on jsreport but looks like it's not recommended</p>
<p>It ends up in too many transactions and slow template deployment/startup since azure file share has a 60mb/s limit on it's default tier</p>
<p>2.2 then I tried git push to app service's local git<br />
app service's local git is at /home/site/repository, by default when you push it sync to /home/site/wwwroot and restart all instances. Looks like this is not restart all but a restart one by one based on my observation, so in theory I don't need deployment slots and deployment can give me 0 downtime.</p>
<p>having WEBSITES_ENABLE_APP_SERVICE_STORAGE turned on makes /home folder shared to all jsreport instances<br />
I made all jsreport to use the /home/site/wwwroot/[myTemplateFolder] as the template store.</p>
<p>now I don't have that 60mb/s issue and I don't need to worry about the per-transaction cost in azure file share</p>
<p>but when I scale-out or git push, some instance randomly dies. After looking at the log it shows there's a concurrency issue during startup on file fs.lock</p>
<p><strong><em>Q: I'm wondering if jsreport can have an option that just take a folder as read-only template-store without creating additional files and monitoring over that folder</em></strong></p>
<p>to resolve this I have to make every instance having it's own local template-store<br />
each instance has it's own /tmp folder and it's cleared during restart.<br />
so I was adding the startup command:<br />
copy /home/site/wwwroot/[myTemplateFolder] to /tmp/[myTemplateFolder]<br />
chown for jsreport to that folder</p>
<p>I believe this was to run at instance level, before jsreport start.<br />
But it ends up in all instance won't start<br />
After a bit research I found azure app service will overwrite docker file's CMD / ENTRYPOINT<br />
so adding &quot;sh <a href="http://run.sh" rel="nofollow">run.sh</a>&quot; (equivalent to CMD[&quot;sh&quot;,&quot;<a href="http://run.sh" rel="nofollow">run.sh</a>&quot;], this is the last step in jsreport's docker file)</p>
<p>now I've got the scale-ability and 0-downtime during deployment</p>
<ol start="3">
<li>Async rendering<br />
some of our system can utilize the async rendering from jsreport but I found it's lack of the [callback] feature so I decided to do this myself.</li>
</ol>
<p>with blob-storage enabled for jsreport, I can have an azure function that is triggered when a blob file is created.<br />
however the blob file name is random so I have to inspect the response of the async rendering to get the report name from url and map the random name with my callback so azure function knows what to do</p>
<p><strong><em>Q: I'm thinking if it's possible to have a callback mechanism from jsreport so I don't need to keep the mapping from the random name to my callback</em></strong></p>
<p>In addition I found a hidden param for the reports extension that blow api call can give me the exact filename, then my azure function can just do blob name-pattern to extract the callback parameters</p>
<p><strong><em>Q: is it safe to use below request? I found that from jsreport repository but it's not mentioned in doco</em></strong><br />
{<br />
&quot;template&quot;: {<br />
&quot;name&quot;: &quot;MyInvoiceTemplate&quot;<br />
},<br />
&quot;options&quot;: {&quot;reports&quot;: {&quot;async&quot;: true, <strong>&quot;blobName&quot;: &quot;invoice112345&quot;</strong>}}<br />
}</p>
]]></description><link>https://forum.jsreport.net/topic/2913/thought-to-share-about-hosting-jsreport-in-azure-app-service-and-questions-about-async-rendering</link><generator>RSS for Node</generator><lastBuildDate>Wed, 20 May 2026 01:36:49 GMT</lastBuildDate><atom:link href="https://forum.jsreport.net/topic/2913.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 30 Aug 2023 04:39:01 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to thought to share about hosting jsreport in azure app service and questions about async rendering on Invalid Date]]></title><description><![CDATA[<p>I'm working on a project that needs to:<br />
move on-prem jsreport instance to azure app service<br />
add template change tracking, in my repository devs can run jsreport that using /[myTempalteStore] as template-store locally</p>
<p>I chose git for template change tracking and here are the issues I got so far and what I did to resolve / found workaround. hope it helps :D</p>
<ol>
<li>
<p>Jsreport docker instance did not respond to warm-up call,<br />
This happens when you scale-out. Every new instance will end up in this.<br />
Restart the instance will work but I don't like restarting each new instance during scale-out<br />
The root cause is when the app service tries to run the docker instance it tries to listen to port 80, ignoring the docker file's specification of 5488<br />
You configure appservice to listen to 5488 instead, using config WEBSITES_PORT</p>
</li>
<li>
<p>template-store issues:<br />
since it's scaled I don't want call api for template deployment for each instance, i need a shared source of truth.</p>
</li>
</ol>
<p>2.1 I first tried azure file share as template store according to the instruction from jsreport home page.<br />
template deployment is done by<br />
-&gt; 2.1.1 azcopying the files from git to azure file share when a commit is pushed<br />
-&gt; 2.2.2 then restart staging-slot<br />
-&gt; 2.3.3 then swap</p>
<p>I don't need 2.1.2 and 2.1.3 if I turn on the external change sync on jsreport but looks like it's not recommended</p>
<p>It ends up in too many transactions and slow template deployment/startup since azure file share has a 60mb/s limit on it's default tier</p>
<p>2.2 then I tried git push to app service's local git<br />
app service's local git is at /home/site/repository, by default when you push it sync to /home/site/wwwroot and restart all instances. Looks like this is not restart all but a restart one by one based on my observation, so in theory I don't need deployment slots and deployment can give me 0 downtime.</p>
<p>having WEBSITES_ENABLE_APP_SERVICE_STORAGE turned on makes /home folder shared to all jsreport instances<br />
I made all jsreport to use the /home/site/wwwroot/[myTemplateFolder] as the template store.</p>
<p>now I don't have that 60mb/s issue and I don't need to worry about the per-transaction cost in azure file share</p>
<p>but when I scale-out or git push, some instance randomly dies. After looking at the log it shows there's a concurrency issue during startup on file fs.lock</p>
<p><strong><em>Q: I'm wondering if jsreport can have an option that just take a folder as read-only template-store without creating additional files and monitoring over that folder</em></strong></p>
<p>to resolve this I have to make every instance having it's own local template-store<br />
each instance has it's own /tmp folder and it's cleared during restart.<br />
so I was adding the startup command:<br />
copy /home/site/wwwroot/[myTemplateFolder] to /tmp/[myTemplateFolder]<br />
chown for jsreport to that folder</p>
<p>I believe this was to run at instance level, before jsreport start.<br />
But it ends up in all instance won't start<br />
After a bit research I found azure app service will overwrite docker file's CMD / ENTRYPOINT<br />
so adding &quot;sh <a href="http://run.sh" rel="nofollow">run.sh</a>&quot; (equivalent to CMD[&quot;sh&quot;,&quot;<a href="http://run.sh" rel="nofollow">run.sh</a>&quot;], this is the last step in jsreport's docker file)</p>
<p>now I've got the scale-ability and 0-downtime during deployment</p>
<ol start="3">
<li>Async rendering<br />
some of our system can utilize the async rendering from jsreport but I found it's lack of the [callback] feature so I decided to do this myself.</li>
</ol>
<p>with blob-storage enabled for jsreport, I can have an azure function that is triggered when a blob file is created.<br />
however the blob file name is random so I have to inspect the response of the async rendering to get the report name from url and map the random name with my callback so azure function knows what to do</p>
<p><strong><em>Q: I'm thinking if it's possible to have a callback mechanism from jsreport so I don't need to keep the mapping from the random name to my callback</em></strong></p>
<p>In addition I found a hidden param for the reports extension that blow api call can give me the exact filename, then my azure function can just do blob name-pattern to extract the callback parameters</p>
<p><strong><em>Q: is it safe to use below request? I found that from jsreport repository but it's not mentioned in doco</em></strong><br />
{<br />
&quot;template&quot;: {<br />
&quot;name&quot;: &quot;MyInvoiceTemplate&quot;<br />
},<br />
&quot;options&quot;: {&quot;reports&quot;: {&quot;async&quot;: true, <strong>&quot;blobName&quot;: &quot;invoice112345&quot;</strong>}}<br />
}</p>
]]></description><link>https://forum.jsreport.net/post/12587</link><guid isPermaLink="true">https://forum.jsreport.net/post/12587</guid><dc:creator><![CDATA[Alan]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[Reply to thought to share about hosting jsreport in azure app service and questions about async rendering on Invalid Date]]></title><description><![CDATA[<p>Thank you for sharing this. As soon as I have some time I will update the documentation.</p>
<blockquote>
<p>but when I scale-out or git push, some instance randomly dies. After looking at the log it shows there's a concurrency issue during startup on file fs.lock</p>
</blockquote>
<p>That is likely because of slow file system.<br />
The error comes from the lock library we use to make sure we don't access the file system in parallel.<br />
<a href="https://github.com/npm/lockfile" rel="nofollow">https://github.com/npm/lockfile</a><br />
The same error is described also here<br />
<a href="https://github.com/npm/lockfile/issues/26" rel="nofollow">https://github.com/npm/lockfile/issues/26</a></p>
<p>The following jsreport configs with defaults are used as options for the locking library.</p>
<pre><code>extensions_fsStore_persistence_lock_stale=5000
extensions_fsStore_persistence_lock_retries=100
extensions_fsStore_persistence_lock_retryWait=100
</code></pre>
<p>You can see we use quite many retries to allow long operations. It looks like the file share has really bad latency in your case. You may still try to increase the retires or change stale to see if it helps.</p>
<blockquote>
<p>Q: I'm wondering if jsreport can have an option that just take a folder as read-only template-store without creating additional files and monitoring over that folder</p>
</blockquote>
<p>I'm afraid this isn't supported. The common solution as you observed is to map the data to some tmp or tmpfs</p>
<blockquote>
<p>Q: I'm thinking if it's possible to have a callback mechanism from jsreport so I don't need to keep the mapping from the random name to my callback</p>
</blockquote>
<p>The callback isn't implemented in the reports extension. I've added it to the backlog.<br />
<a href="https://github.com/jsreport/jsreport/issues/1091" rel="nofollow">https://github.com/jsreport/jsreport/issues/1091</a><br />
If you have any suggestions about how the callback request should look like and how it should be configured, please add it to github issue.</p>
<p>I've seen somewhere here a guy solving this using jsreport script and after render hook.<br />
<a href="https://jsreport.net/learn/scripts" rel="nofollow">https://jsreport.net/learn/scripts</a></p>
<blockquote>
<p>Q: is it safe to use below request? I found that from jsreport repository but it's not mentioned in doco</p>
</blockquote>
<p>Yes.</p>
]]></description><link>https://forum.jsreport.net/post/12594</link><guid isPermaLink="true">https://forum.jsreport.net/post/12594</guid><dc:creator><![CDATA[admin]]></dc:creator><pubDate>Invalid Date</pubDate></item></channel></rss>