This is a general outline for using a headless CMS (such as Contentful).
There are other ways to do this but this is fast given a suitable size delta, and will recover from failure better than webhooks:
This has the headless CMS being polled by a Static Site Generator.
The Static Site Generator knows the current state of the site and only regenerates changed items. This may require it to keep a map of dependencies between nodes. Sometimes you may need to go 3 or 4 levels deep. Store the output in S3. Serve the website from S3, which allows some customisation of the data. Use a CDN to back the website to reduce load. Purge the pages of the site that have changed after they have been written.
We managed to use a single Heroku node for the SSG and another one for the webserver.
This provides a simple decorating wrapper that records the time that the database call took without making the code less readable.
This could be made more sophisticated using:
def warnSlow(String message, def max_duration_in_seconds = 5, Closure body) { def start = Instant.now() def result = body.call() def finish = Instant.now() Duration duration = Duration.between(start, finish) if (duration.getSeconds() > max_duration_in_seconds) { warn “$message is slow, it took $duration which is longer than the threshold of $max_duration_in_seconds” } result }
This permits simple performance checks to be added to code with minimal disruption.
The project that I currently work on uses a number of microservices. Several of these microservices use MongoDB. The platform provider that we are using to host these databases (compose.io) has announced that they are going to stop supporting Mongo in about two months time.
This has resulted in a thorough investigation of the mongo databases that we are using.
Several of the services use the following architecture:
This has three instances of an application that periodically poll a website before performing sending the result to rabbitmq. They use the mongodb as a lock so that only one of the three perform the operation.
The alternative design was to add an external scheduler to trigger the nodes. The load balancer would pick one of the nodes to perform the work. One of my colleagues pointed out that we could use a lambda to do this. Lambdas are (typically) javascript functions that are cloud hosted.
It it is possible to deploy a lambda with a schedule of how frequently it should be invoked, either with a given frequency or via a CRON-like specification. The lambdas invoke methods on the nodes that asynchronously trigger the process.
Here is a diagram of the replacement:
This has allowed us to replace three MongoDB’s in each of four environments with a much simpler lambda function.
In addition we have been able to remove the mongodb database driver and the internal cron scheduling components. This greatly simplifies these services. There is now less to maintain (less PR’s from dependabot). It is also far easier to test code that is called from an endpoint than one from a scheduled event.
We do still need to replace the remaining MongoDB’s which contain real data but this is a much more manageable job.
We also learned that AWS still uses Node 8 LTS for Lambda.
This is a great starting point for serverless functions.