`create_history` used to initialise an empty model instance and
assign attributes to it one by one. Assigned attributes are
collected by iterating over internal state of the modified record
and stored in a dictionary, so the order in which they are set on
the history instance is undefined.
This works fine for most model instances, but recent changes to the
Template models require `template_type` to be set before `reply_to`,
otherwise Template doesn't know which column to use to persist the
`reply_to` value.
This means that we need to order the attributes when they're being
assigned. We achieved this by defining a constructor for Template
objects that assigns `template_type` first.
In order to make it work with `create_history` we replace individual
`setattr` calls with a single call to the Template constructor which
passes the entire data dictionary as keyword arguments.
This works because all persisted attributes are defined as columns
and SQLAlchemy accepts all column values as constructor arguments.
Increasing the Gunicorn workers to 10 actually made the API decrease
in performance from ~200 requests/sec with with 20 API instances to
150 requests per/sec. The base value is 5 so this is to test how the API
performs with a slight increase.
Increased Gunicorn threads to 10 on staging to test if there is a
performance increase when testing request per second. Increased to 10.
Gunicorn recommend 2 x cores + 1 however on PaaS the number of cores
is not consistent.
* unused variables
* variables in loops overshadowing imports
* excepts with no defined exc type (tried to avoid `except Exception` too)
* history mapper is still too complex
* default variables should never be mutable
(saves us having to write the stuff ourselves). Also adds a small
click plugin to do datetime parsing.
Sample output:
```
[leohemsted:~/dev/api]$ flask command create_provider_rates --help
Usage: flask command create_provider_rates [OPTIONS]
Backfill rates for a given provider
Options:
-p, --provider_name [mmg|firetext|ses]
[required]
-c, --cost FLOAT Cost (pence) per message including decimals
[required]
-d, --valid_from DATE [required]
--help Show this message and exit.
[leohemsted:~/dev/api]$ flask command create_provider_rates -p ses -c 1.234 -d invalid
Usage: flask command create_provider_rates [OPTIONS]
Error: Invalid value for "-d" / "--valid_from": Could not parse datetime string "invalid" formatted as %Y-%m-%dT%H:%M:%S
```