Removing overhead of ADRs for the timebeing They will be more for
changes after initial program is completed. Signed-off-by: Cliff Hill <xlorep@darkhelm.org>
This commit is contained in:
@@ -1,26 +0,0 @@
|
||||
# ADR 001: Pick a good concurrency solution
|
||||
|
||||
The application has several components that would benefit from concurrency. The four options looked at are:
|
||||
|
||||
1. Synchronous - no concurrency at all, everything in a single thread, executed in sequence.
|
||||
2. Threading - OS threading concurrency, with the GIL limiting to a single thread being able to use the processor at one time.
|
||||
3. Multiprocessing - Independent full Python processes, usually pointlessly expensive beyond the number of cores the system has.
|
||||
4. Asynchronous - Single-thread, but with cooperative concurrency allowing typically for processes to be able to wait for something, like I/O easily.
|
||||
|
||||
## Decision
|
||||
|
||||
The application will be written using an asynchronous design. Selection of other libraries to use for the application will be focused on asynchronous libraries whenever possible. If no asynchronous library is possible/available, the use of threadpools and processpools will be determined on a case-by-case manner.
|
||||
|
||||
## Rationale
|
||||
|
||||
The best approach would be to use async, as this gives the most flexibility. With the use of ThreadPools and ProcessPools, it can allow for synchronous/blocking code to become non-blocking with threads/processes dividing up the work. It does not have the limitations that could be imposed on threading or multiprocessing, and there is wide-spred acceptance of async in Python now.
|
||||
|
||||
It is better to choose async up-front, as the conversion from sync to async is a major burden, it is easier to start with it from the start.
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Consequences
|
||||
|
||||
There will likely be complications as expected from any concurrency operations which will need to be dealt with when they arise. It is important to write as much code using coroutines as possible to avoid blocking issues, and to remember to `await` them when calling them.
|
||||
@@ -1,24 +0,0 @@
|
||||
# ADR 002: Choose a good configuration format.
|
||||
|
||||
A good configuration file format needs to be selected. There are three main choices that were considered:
|
||||
|
||||
1. JSON - this is the primary data format used for the web and communications, but is not as readable as the other options.
|
||||
2. YAML - this is a much more readable format, and is a superset of JSON (able to load JSON as YAML), however there are weird nuances in this format that can cause problems.
|
||||
3. TOML - this is a format similar to the old Windows Config format, but with better structuring. It is readable, and clear like YAML, but without the weird corner cases that YAML has which could break things. However support is small as it is relatively new.
|
||||
4. SQL DB Table - this would be using the database system to store what would have been put in a configuration file and making it instead be a configuration table.
|
||||
|
||||
## Decision
|
||||
|
||||
SQL DB Table
|
||||
|
||||
## Rationale
|
||||
|
||||
Because the system already is using an SQL Database, it makes sense to use a SQL table to store these values in a simple way that then can be retrieved and updated using the same basic SQL components other parts of the application use. Actual application configuration would be through environment variales to comply with the 12-factor app.
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Consequences
|
||||
|
||||
Setting up the database already was necessary for the application, this would simply require it to be set up sooner.
|
||||
@@ -1,21 +0,0 @@
|
||||
# ADR 003: database type & selection
|
||||
|
||||
There are multiple different database systems that exist with Python integration in them. Both NoSQL and SQL. This will be an effort to select the correct one for the application.
|
||||
|
||||
## Decision
|
||||
|
||||
After review of the options, the database that was selected was PostgreSQL. It is a relational SQL database, which is very mature and is a very good system to use for things.
|
||||
|
||||
## Rationale
|
||||
|
||||
There are questionable and uncertain problems with using a NoSQL system, and it really doesn't lend itself to being used in this particular application, so it was determined to not use NoSQL as it doesn't give any benefits and has a possiblity to make things harder/more complicated. PostgreSQL was selected as it has some very good asynchronous drivers for Python and will make using it simpler. Plus the developer is far more familiar with it than other systems.
|
||||
|
||||
Because we are using an asynchronous system, the `asyncpg` library will be used. This is because it is the fastest of the async PostgreSQL drivers.
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Consequences
|
||||
|
||||
At this time, it isn't certain what negative consequences will arise. Code will be implemented in as database-agnostic a way as possible in order to facilitate a switch of backend if needed.
|
||||
@@ -1,19 +0,0 @@
|
||||
# ADR 004: select SQL API to use to build database code with
|
||||
|
||||
SQL should be implemented in such a manner as to be databaase-agnostic, so the correct selection of a SQL tool is essential. Further, it needs to be something that can work asynchronously in Python.
|
||||
|
||||
## Decision
|
||||
|
||||
SQLAlchemy 2+ is selected.
|
||||
|
||||
## Rationale
|
||||
|
||||
This is the future of SQLAlchemy, it combines the Core and ORM components making it easier to build out SQL code.
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Consequences
|
||||
|
||||
SQLAlchemy 2's async functionality is still a bit rough, but will improve over time. As such it might be a little finicky in making things work. This is an accepted tech debt.
|
||||
@@ -1,19 +0,0 @@
|
||||
# ADR 005: select cryptographic library
|
||||
|
||||
It is important to be able to encrypt data to be stored in the database to protect it from being accessed by bad actors.
|
||||
|
||||
## Decision
|
||||
|
||||
The cryptography library was selected.
|
||||
|
||||
## Rationale
|
||||
|
||||
The cryptography library is a pretty standard library to use in Python for cryptographic purposes.
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Consequences
|
||||
|
||||
This is not an asynchronous library. As syuch, we will need to make it non-blocking with the use of a ThreadPool while cryptographic functions are called.
|
||||
@@ -1,19 +0,0 @@
|
||||
# ADR 006: choose plex api for Python
|
||||
|
||||
As this project is to use the Plex system to interact with and make a playlist for, it needs to be able to access the Plex server.
|
||||
|
||||
## Decision
|
||||
|
||||
plexapi will be used.
|
||||
|
||||
## Rationale
|
||||
|
||||
There really is only one api for Plex in Python.
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Consequences
|
||||
|
||||
This is not an asynchronous API, it is going to need to have parts of it wrapped with a ThreadPool to run savely and without blocking the rest of the application.
|
||||
@@ -1,19 +0,0 @@
|
||||
# ADR 007: serialization and validation library
|
||||
|
||||
Converting the data from the database into something that can be serialized, as well as validating that the data is correct is essential to the application. Two main libraries were looked at: `marshmallow` and `pydantic`.
|
||||
|
||||
## Decision
|
||||
|
||||
The `pydantic` library will be used.
|
||||
|
||||
## Rationale
|
||||
|
||||
Despite the merits of the `marshmallow` library, the `pydantic` library works better with SQLAlchemy 2.0+ and works well with type hints.
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Consequences
|
||||
|
||||
Not sure at this time what ramifications will arise from this decision.
|
||||
@@ -1,23 +0,0 @@
|
||||
# ADR 008: model class definition
|
||||
|
||||
Database models can be constructed in a few different ways in SQLAlchemy.
|
||||
|
||||
## Decision
|
||||
|
||||
DB Models will be defined as dataclasses.
|
||||
|
||||
## Rationale
|
||||
|
||||
Dataclasses are a useful addition to Python providing a variety of features up-front, as well as being a standard that is used in a variety of different libraries. As such, it is essential to use this for defining the data structures to make them as clear and "future-proof" as possible.
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Consequences
|
||||
|
||||
Not sure at this time. Dataclass implementation in SQLAlchemy is a new thing.
|
||||
|
||||
Because of issues surrounding the differences between Pydantic and SQLAlchemy's models, these will likely need to be separate at this time. Eventually, when SQLModel gets updated to handle Pydantic 2.0+ and SQLAlchemy 2.0+, then this can be revised and updated to use SQLModel.
|
||||
|
||||
see: https://docs.sqlalchemy.org/en/20/orm/dataclasses.html#integrating-with-alternate-dataclass-providers-such-as-pydantic
|
||||
@@ -1,19 +0,0 @@
|
||||
# ADR 009: Database Migrations
|
||||
|
||||
Database migrations will be important as the system evolves and changes, in order to protect the database and allow for everything to flow nicely.
|
||||
|
||||
## Decision
|
||||
|
||||
Alembic will be used for the database migrations.
|
||||
|
||||
## Rationale
|
||||
|
||||
Alembic is the defacto standard for SQLAlchemy migrations.
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Consequences
|
||||
|
||||
Maintaining the SQL migrations will be key in order to ensure that the database is safely updated with changes as the code advances. It will be imperitive to keep the migrations up as the system is developed.
|
||||
Reference in New Issue
Block a user