RosaeNLG / rosaenlg

RosaeNLG is a Natural Language Generation library for node.js and browser rendering, based on the Pug template engine.
https://rosaenlg.org
Apache License 2.0
92 stars 21 forks source link

Why do we need sha1 when consuming the API? #92

Open oytuntez opened 3 years ago

oytuntez commented 3 years ago

Hi there,

Thank you for your work in this very practical library. I've been enjoying the documentation and actually just finalized generating a large test content now.

I have one question: sha1 hashes. Why do we need to expose them to the outside? It makes the client experience so much harder. Basically, one needs to re-deploy the client that uses RosaeNLG if a template is updated to call the API with the proper sha1 hash.

At first, I thought the API was keeping versions, so sha1 allowed clients to use multiple versions of a template, but that is not the case. What do you think of adding another render endpoint, only with the template name, without requiring clients to know about its sha1?

Oytun

oytuntez commented 3 years ago

Or it just forces clients to make a couple more API calls to first get the sha1 of the template, and then another call to render with that sha1.

ludans commented 3 years ago

Thanks!

Yes, sha1 hashes make experience harder. They were not here at the beginning, I hesitated a lot to add them, but I added for one reason.

Let's have an architecture with a load balancer and multiple RosaeNLG instances behind it. Each instance must be able to render any template. They are loaded automatically and cached at first render call.

The problem is the following: when a template gets updated, only once instance (the one that receives the new template) is aware and can update its cache. The others instances would keep serving outdated templates.

When sending a new sha1 to instances with an outdated cache, these instances are able to see it that they don't have the proper version and smoothly reload the template and update their cache.

There are probably other ways to do it but which would probably imply instance to instance communication, which I would like to avoid.

In practice, there are ways to cope with sha1 transparently in the code:

Also, another option is to not use the API to deploy new versions of the templates, but to bundle docker images that contain RosaeNLG and its templates, using CI/CD, as (somewhat) described here: https://rosaenlg.org/rosaenlg/3.0.1/dev_experience.html#_deploy_to_use_as_an_api

oytuntez commented 3 years ago

Hey Ludan,

Thanks for the explanation, it makes sense (and of course there is some space for improvement here for cache invalidations).

I don’t think we will ever need to run Rosae in a cluster, if I send a PR for an endpoint without sha1, would you be willing to merge it? We can document it just like you did in the documentation regarding the cache in cluster mode (using lazy load warning).

Let me know what you think, Oytun

On Thu, Aug 5, 2021 at 1:39 PM Ludan Stoecklé @.***> wrote:

Thanks!

Yes, sha1 hashes make experience harder. They were not here at the beginning, I hesitated a lot to add them, but I added for one reason.

Let's have an architecture with a load balancer and multiple RosaeNLG instances behind it. Each instance must be able to render any template. They are loaded automatically and cached at first render call.

The problem is the following: when a template gets updated, only once instance (the one that receives the new template) is aware and can update its cache. The others instances would keep serving outdated templates.

When sending a new sha1 to instances with an outdated cache, these instances are able to see it that they don't have the proper version and smoothly reload the template and update their cache.

There are probably other ways to do it but which would probably imply instance to instance communication, which I would like to avoid.

In practice, there are ways to cope with sha1 transparently in the code:

  • make a first GET call to get information about the template (including the sha1)
  • even better, make a render call with a random sha1 (e.g. 'aaa'): you will get a 308 with the proper sha1, that you can keep afterwards (this is what I do)

Also, another option is to not use the API to deploy new versions of the templates, but to bundle docker images that contain RosaeNLG and its templates, using CI/CD, as (somewhat) described here: https://rosaenlg.org/rosaenlg/3.0.1/dev_experience.html#_deploy_to_use_as_an_api

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/RosaeNLG/rosaenlg/issues/92#issuecomment-893353797, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAFAJ666NBFRPE73DPLRKU3T3JS4JANCNFSM5BSUY7OA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .

-- Sent from mobile.

oytuntez commented 3 years ago

Btw, we’ll soon put this whole thing in our CI/CD, but I don’t think we’ll deploy a whole new container, it takes too much time for such a small change. We will probably upload the templates to the server (single node, no cluster) and reload its cache. I’m hoping that we won’t need to fork your current Docker container.

On Thu, Aug 5, 2021 at 1:43 PM Oytun Tez @.***> wrote:

Hey Ludan,

Thanks for the explanation, it makes sense (and of course there is some space for improvement here for cache invalidations).

I don’t think we will ever need to run Rosae in a cluster, if I send a PR for an endpoint without sha1, would you be willing to merge it? We can document it just like you did in the documentation regarding the cache in cluster mode (using lazy load warning).

Let me know what you think, Oytun

On Thu, Aug 5, 2021 at 1:39 PM Ludan Stoecklé @.***> wrote:

Thanks!

Yes, sha1 hashes make experience harder. They were not here at the beginning, I hesitated a lot to add them, but I added for one reason.

Let's have an architecture with a load balancer and multiple RosaeNLG instances behind it. Each instance must be able to render any template. They are loaded automatically and cached at first render call.

The problem is the following: when a template gets updated, only once instance (the one that receives the new template) is aware and can update its cache. The others instances would keep serving outdated templates.

When sending a new sha1 to instances with an outdated cache, these instances are able to see it that they don't have the proper version and smoothly reload the template and update their cache.

There are probably other ways to do it but which would probably imply instance to instance communication, which I would like to avoid.

In practice, there are ways to cope with sha1 transparently in the code:

  • make a first GET call to get information about the template (including the sha1)
  • even better, make a render call with a random sha1 (e.g. 'aaa'): you will get a 308 with the proper sha1, that you can keep afterwards (this is what I do)

Also, another option is to not use the API to deploy new versions of the templates, but to bundle docker images that contain RosaeNLG and its templates, using CI/CD, as (somewhat) described here: https://rosaenlg.org/rosaenlg/3.0.1/dev_experience.html#_deploy_to_use_as_an_api

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/RosaeNLG/rosaenlg/issues/92#issuecomment-893353797, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAFAJ666NBFRPE73DPLRKU3T3JS4JANCNFSM5BSUY7OA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .

-- Sent from mobile.

  • MotaWord
  • Güzel İşler Derneği
  • Parva Bergama

-- Sent from mobile.

ludans commented 3 years ago

Render without sha1 would:

I would be happy to have a PR with it. Please

For your target, you say: We will probably upload the templates to the server (single node, no cluster) and reload its cache. I would rather use the API endpoint that does all the job: The template is validated, loaded, autotested (if configured so), and saved on disk or S3 if persistent storage is set.

oytuntez commented 3 years ago

Perfect! Let us start using this on production, get a taste of it, and then I’ll start with PRs soon.

On Thu, Aug 5, 2021 at 2:03 PM Ludan Stoecklé @.***> wrote:

Render without sha1 would:

  • load the template if it is not in the cache yet
  • or render whatever it has in its cache (considering its cache is always good)

I would be happy to have a PR with it. Please

  • add test cases :)
  • add documentation :)

For your target, you say: We will probably upload the templates to the server (single node, no cluster) and reload its cache. I would rather use the API endpoint that does all the job: The template is validated, loaded, autotested (if configured so), and saved on disk or S3 if persistent storage is set.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/RosaeNLG/rosaenlg/issues/92#issuecomment-893367485, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAFAJ632HRXVKLPAF7XVLJ3T3JVYJANCNFSM5BSUY7OA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .

-- Sent from mobile.

reinoldus commented 2 years ago

For people trying to get docker deployment done in one CI step:

If you used the "yo" template as given in the docs, you should be able to use this Dockerfile to get pre-compiled templates working in your docker container:

FROM rosaenlg/server:3.2.0
COPY package.json /
COPY package-lock.json /
RUN npm i
COPY ./ /
RUN npx gulp package

FROM rosaenlg/server:3.2.0
ENV ROSAENLG_HOMEDIR=/templates
RUN mkdir /templates
COPY --from=0 /dist/ ./templates/
RUN cd /templates && for i in *.json; do mv $i "DEFAULT_USER#$i";done && cd -

It uses a multi stage docker build. First stage, we copy the local "yo" project and run the steps as described in the docs via gulp package.

Second step: Copy the files from the first stage into the final stage in the "/templates" directory. The server then should start with the compile messages.

All templates then can be accessed using a "random" sha1 hash.

ludans commented 2 years ago

Thanks @reinoldus for this docker recipe. I have added this in the documentation, PR is https://github.com/RosaeNLG/rosaenlg/pull/118 . It will be included in the next release.