Support team updates professional subscription terms for some customer.
Those changes require activated instances to refresh their license, which should be a transparent process not requiring from instance administrator to execute any manual action.
Currently, license is auto-refreshed in case any of its limit has been reached. For example, if the license was created with 10 concurrent users limitation, when 11th user is tried to log in concurrently, before preventing their login, it is checked whether the license has been upgraded to support more users.
If no limit is reached, license gets never automatically refreshed.
Ideally, those changes should be immediately pushed to all the instances that are activated with that license.
Due to technical restrictions it is not possible to trigger those pushed from butler to instances as there is not a direct communication channel in this direction.
Alternatively, instances will daily check if there are changes in their license to download them. Every first login after 24 hours since last refresh will automatically trigger license to be refreshed.
Whenever license is refreshed, butler computes information, generates it, encrypts and sends it. This full process takes ~400ms (most of them to perform encryption), not taking into account network latency.
This has some problems:
- We can expect a considerable traffic increase in butler for these requests
- Currently this occurs in a synchronized block so that while refreshing license, the rest of threads are awaiting it to be completed till they can be processed. This, which so far, has not been a big issue because refresh occurred only in some exceptional cases, can be expected to dramatically change as every 24hr there will be requests for update.
Changes to solve the problem
In most of the cases there will not be changes in the license, so all this request will result in a noop update.
From now on, butler will include in the license, the timestamp with the latest change affecting the license itself. This timestamp will be sent back in auto-refreshe requests, only if it changed the license will be generated as currently is. Other case a "NoChange" message will be sent back to instance. This reduces, in case of no change, the time to process to ~6ms.
In addition, Openbravo will only lock one thread while refreshing, if while refreshing there are new requests, they will be processed using old license. So at most, one thread, will be waiting the process in butler to complete.
License information is kept in JVM memory within ActivationKey singleton class, being a singleton class means there will be as many instances as different JVMs running, this is one per node in case of Openbravo is run in a Tomcat cluster.
It is required to ensure that in case of license is refreshed from a node, the rest of the nodes get also refreshed in an acceptable amount of time.
To accomplish this, whenever the license is refreshed, timestamp will also be stored in DB. On login, this timestamp will be checked and if it differs, license will be reloaded from DB. In this manner the stale information in different nodes will, at most, be for the already existing sessions, but any new session created in any node will have updated license.