I'm working on a project that needs to:
move on-prem jsreport instance to azure app service
add template change tracking, in my repository devs can run jsreport that using /[myTempalteStore] as template-store locally
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
-
Jsreport docker instance did not respond to warm-up call,
This happens when you scale-out. Every new instance will end up in this.
Restart the instance will work but I don't like restarting each new instance during scale-out
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
You configure appservice to listen to 5488 instead, using config WEBSITES_PORT -
template-store issues:
since it's scaled I don't want call api for template deployment for each instance, i need a shared source of truth.
2.1 I first tried azure file share as template store according to the instruction from jsreport home page.
template deployment is done by
-> 2.1.1 azcopying the files from git to azure file share when a commit is pushed
-> 2.2.2 then restart staging-slot
-> 2.3.3 then swap
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
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
2.2 then I tried git push to app service's local git
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.
having WEBSITES_ENABLE_APP_SERVICE_STORAGE turned on makes /home folder shared to all jsreport instances
I made all jsreport to use the /home/site/wwwroot/[myTemplateFolder] as the template store.
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
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
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
to resolve this I have to make every instance having it's own local template-store
each instance has it's own /tmp folder and it's cleared during restart.
so I was adding the startup command:
copy /home/site/wwwroot/[myTemplateFolder] to /tmp/[myTemplateFolder]
chown for jsreport to that folder
I believe this was to run at instance level, before jsreport start.
But it ends up in all instance won't start
After a bit research I found azure app service will overwrite docker file's CMD / ENTRYPOINT
so adding "sh run.sh" (equivalent to CMD["sh","run.sh"], this is the last step in jsreport's docker file)
now I've got the scale-ability and 0-downtime during deployment
- Async rendering
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.
with blob-storage enabled for jsreport, I can have an azure function that is triggered when a blob file is created.
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
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
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
Q: is it safe to use below request? I found that from jsreport repository but it's not mentioned in doco
{
"template": {
"name": "MyInvoiceTemplate"
},
"options": {"reports": {"async": true, "blobName": "invoice112345"}}
}