Facade for the OpenAlchemy package database
Project description
Database
The database has a facade exposes a series of functions that enable services to personalize responses.
Interface
The interface for the database is defined as the TDatabase
class here:
open_alchemy/package_database/types.py
It can be retrieved using:
from open_alchemy import package_database
database_instance = package_database.get()
Note that the STAGE
environment variable needs to be set. The possible
values are:
TEST
: DynamoDB is assumed to be running at http://localhost:8000PROD
: a connection is established to the AWS hosted DynamoDB
Tables
Specs
Stores information about the specs for a user. The following access patterns are expected:
- count the number of models for a user,
- create or update a spec record for a user,
- get the latest version of a spec for a user,
- list all specs for a user,
- retrieve a particular spec for a user,
- delete a particular spec for a user,
- list all versions of a spec for a user and
- delete all specs for a user.
Count Models for a User
Counts the number of models a user has defined.
Input:
sub
: unique identifier for the user.
Output:
- The sum of the latest
model_count
for each spec for the user.
Algorithm:
- filter by the
sub
andupdated_at_id
to start withlatest#
and - sum over the
model_count
of each record.
Create or Update a Spec
Input:
sub
,name
: the name of the spec,version
: the version of the spec,model_count
: the number of models in the spec,title
(optional): the title of the spec anddescription
(optional): the description of the spec.
Output:
Algorithm:
- calculate the
id
of the spec using https://packaging.pypa.io/en/latest/utils.html#packaging.utils.canonicalize_name based on thename
, - calculate
updated_at
based on he current EPOCH time using https://docs.python.org/3/library/time.html#time.time and convert to an integer represented as a string, - calculate the value for
updated_at_id
by joining a zero paddedupdated_at
to 20 characters andid
with a#
and forid_updated_at
by joiningid
andupdated_at
with a#
, - save the item to the database,
- create another item but use
latest
forupdated_at
when generatingupdated_at_id
andid_updated_at
Get Latest Spec Version
Retrieve the latest version of a spec.
Input:
sub
andname
.
Output:
- The latest
version
of the spec.
Algorithm:
- calculate the
id
of the spec using https://packaging.pypa.io/en/latest/utils.html#packaging.utils.canonicalize_name based on thename
, - Retrieve the item using the
sub
partition key andupdated_at_id
sort key equal tolatest#<id>
and - return the version of the item.
List Specs
Returns information about all the available specs for a user.
Input:
sub
.
Output:
- A list of dictionaries with the
id
,name
,updated_at
,version
,model_count
andtitle
anddescription
if they are defined.
Algorithm:
- filter items using the
sub
partition key andupdated_at_id
starting withlatest#
and - convert the items to dictionaries.
Get Spec
Retrieve a particular spec for a user.
Input:
sub
andname
.
Output:
- dictionary with the
id
,name
,updated_at
,version
,model_count
andtitle
anddescription
if they are defined
Algorithm:
- calculate the
id
of the spec using https://packaging.pypa.io/en/latest/utils.html#packaging.utils.canonicalize_name based on thename
, - get the item based on
sub
andupdated_at_id
with the valuelatest#<id>
, - handle the case where it is not found by returning
None
and - convert the item to a dictionary.
Delete Spec
Delete a particular spec for a user.
Input:
sub
andname
.
Output:
Algorithm:
- calculate the
id
of the spec using https://packaging.pypa.io/en/latest/utils.html#packaging.utils.canonicalize_name based on thename
, - query the
id_updated_at_index
local secondary index by filtering forsub
andid_updated_at
starting with<id>#
and - delete all returned items.
List Spec Versions
Returns information about all the available versions of a spec for a user.
Input:
sub
andname
.
Output:
- A list of dictionaries with the
id
,name
,updated_at
,version
,model_count
andtitle
anddescription
if they are defined.
Algorithm:
- calculate the
id
of the spec using https://packaging.pypa.io/en/latest/utils.html#packaging.utils.canonicalize_name based on thename
, - query the
id_updated_at_index
local secondary index by filtering forsub
andid_updated_at
starting with<id>#
, - filter out any items where
updated_at_id
starts withlatest#
and - convert the items to dictionaries.
Delete All Specs for a User
Input:
sub
.
Output:
Algorithm:
- Delete all entries for
sub
.
Spec Properties
sub
: A string that is the partition key of the table.id
: A string.name
: A string.updated_at
: A string.version
: A string.title
: An optional string.description
: An optional string.model_count
A number.updated_at_id
: A string that is the sort key of the table.id_updated_at
: A string that is the sort key of theidUpdatedAt
local secondary index of the table.
Credentials
Stores credentials for a user. The following access patterns are expected:
- list available credentials for a user,
- create or update credentials for a user,
- retrieve particular credentials for a user,
- check that a public and secret key combination exists and retrieve the
sub
for it, - delete particular credentials for a user and
- delete all credentials for a user.
List Credentials
List all available credentials for a user.
Input:
sub
.
Output:
- list of dictionaries with the
id
,public_key
andsalt
keys.
Algorithm:
- use the
sub
partition key to retrieve all credentials for the user and - map the items to a dictionary.
Create or Update Credentials
Create or update credentials for a user.
Input:
sub
: unique identifier for the user,id
: unique identifier for the credentials,public_key
: public identifier for the credentials,secret_key_hash
: a hash of the secret key for the credentials that is safe to store,salt
: a random value used to generate the credentials.
Output:
Algorithm:
- create and store an item based on the input.
Retrieve Credentials
If the credential with the id exists, return it. Otherwise, return None
.
Input:
sub
: unique identifier for the user andid
: unique identifier for the credential.
Output:
id
,public_key
,salt
.
Algorithm:
- Use the
sub
partition key andid
sort key to check whether an entry exists, - if an entry exists, return the
public_key
andsalt
and - return
None
.
Retrieve User
Check that the public key exists and retrieve the user and salt for it.
Input:
public_key
.
Output:
sub
,salt
andsecret_key_hash
.
Algorithm:
- check whether an entry exists using the
public_key
partition key for thepublicKey
global secondary index - if it does not exist, return
None
and - retrieve and return the
sub
,salt
andsecret_key_hash
.
Delete a Credential for a User
Input:
sub
andid
.
Output:
Algorithm:
- Delete all entries for
sub
andid
.
Delete All Credentials for a User
Input:
sub
.
Output:
Algorithm:
- Delete all entries for
sub
.
Credentials Properties
sub
: A string that is the partition key of the table.id
: A string that is the sort key of the table.public_key
: A string that is the partition key of thepublicKey
global secondary index.secret_key_hash
: Bytes.salt
: Bytes.
test
Executes the tests defined at tests.
build
Builds the database package defined at ..
release-required
Has 2 outputs:
result
: whether a release to PyPI is required based on the latest released version and the version configured in the project andproject-version
: the version configured in the code base.
deploy
Deploys the CloudFormation stack for the database defined at ../infrastructure/lib/database-stack.ts.
release
If the result
output from release-required
is true, the package is deployed
to both test and production PyPI.
Irrespective of whether the release was executed, the version of the package defined in the code base is installed from both test and production PyPI and the tests defined at ../test/database/tests are executed against the deployed infrastructure on AWS.
Periodic Production Tests
The workflow is defined here: ../.github/workflows/production-test-database.yaml.
Executes the tests defined at ../test/database/tests against a configured version of the package and against the currently deployed infrastructure on AWS.
Pytest Plugin
A pytest plugin is made available to make testing easier. It is defined at open_alchemy/package_database/pytest_plugin.py.
It requires the dynalite
NPM package to be installed in the project using
npm install --save-dev dynalite
to run a local dynamoDB instance at
http://localhost:8000. More information on the package is here:
https://www.npmjs.com/package/dynalite.
Fixtures
All fixtures that have an effect but yield None
are prefixed with _
so that
tools like pylint do not complain about unused arguments for test functions.
_database
Spins up the database at the start of the tests and tars down the database at
the end. This fixture is unlikely to be useful as no tables are created. The
table specific fixtures depend on the _database
fixture so it is not
necessary to include this fixture in any tests.
_specs_table
Creates the package.specs
table before all the tests and deletes it after all
tests complete.
_clean_specs_table
Deletes all items from the package.specs
table before and after each test.
_credentials_table
Creates the package.credentials
table before all the tests and deletes it after
all tests complete.
_clean_credentials_table
Deletes all items from the package.credentials
table before and after each
test.
Infrastructure
The CloudFormation stack is defined here: ../infrastructure/lib/database-stack.ts.
CI-CD
The workflow is defined here: ../.github/workflows/ci-cd-database.yaml.
There are a few groups of jobs in the CI-CD:
test
: runs the tests for the package in supported python versions,build
: builds the database package,deploy
: deploys database infrastructure to AWS,release-required
: determines whether a release to PyPI is required andrelease
: a combination of deploying to test and production PyPI and executing tests on the published packages
Production Tests
The tests against the deployed database facade are defined here: ../test/database/.
The workflow that periodically executes the tests is defined here: ../.github/workflows/production-test-database.yaml.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file open-alchemy.package-database-4.0.1.tar.gz
.
File metadata
- Download URL: open-alchemy.package-database-4.0.1.tar.gz
- Upload date:
- Size: 14.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/51.1.2 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.8.7
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 892c97e8773d4a21270d6dce9659222f56290e1d2abb09c8a08db19a56584ac1 |
|
MD5 | 81a6b9c7e11012edffb0cc77f676a5ee |
|
BLAKE2b-256 | fde4ceecbb0f76295f0af9ee2c970acfa39d3ab2e140c3748417a9ea082ab9cb |
File details
Details for the file open_alchemy.package_database-4.0.1-py3-none-any.whl
.
File metadata
- Download URL: open_alchemy.package_database-4.0.1-py3-none-any.whl
- Upload date:
- Size: 14.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/51.1.2 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.8.7
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5cc3e044e1dd342ce6e493470b78012e0ae36c85a90cdb29154185e73e6a0914 |
|
MD5 | 7c5760e74d910810010271189278492e |
|
BLAKE2b-256 | da3c87cc36bae03d152b378b680923f3c0182af130694d978f60800f65fe6cef |