Auditing/versioning v2#510
Conversation
* origin/main: Update `brain-atlas` endpoints (#506) Add published_in filter in ScientificArtifact (#505) Make nullable attributes of EMDenseReconstructionDataset (#503) Remove all endpoints that had a `InBrainRegionDep`, but don't have a brain_region_id (#501) Add pref_label/alt_label ilike_search to ETypeClass/MTypeClass filters (#500) add `number_neurons` to Simulation` (#493) Fix incorrect returned values when getting `ascendants_and_descendants` (#498)
c94f464 to
551232b
Compare
551232b to
11b4e29
Compare
Codecov Report❌ Patch coverage is
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 1 file with indirect coverage changes 🚀 New features to boost your workflow:
|
| read_mtypes_history = router.get("/{id_}/mtypes/history")( | ||
| app.service.cell_morphology.read_mtypes_history | ||
| ) |
There was a problem hiding this comment.
This is just an example, it's going to be removed.
| ) | ||
|
|
||
|
|
||
| def read_mtypes_history( |
There was a problem hiding this comment.
Same here.
mgeplf
left a comment
There was a problem hiding this comment.
No red flags, sqlalchemy-history seems to not be too intrusive considering what it unlocks; very impressive.
| # FIXME: # noqa: FIX001 | ||
| # the creation of a new agent would fail with: Session is already flushing | ||
| # so the user_id is logged only if it already exists. | ||
| # Alternative: ensure that the person is created at the beginning of the request, |
There was a problem hiding this comment.
is the Alternative a note to yourself and should be removed? If not, I don't follow it.
| required-version = ">=0.8.0" | ||
|
|
||
| [tool.uv.sources] | ||
| sqlalchemy-history = { git = "https://github.com/GianlucaFicarelli/sqlalchemy-history", branch = "obi" } |
There was a problem hiding this comment.
should this be forked into OBI?
| TransactionChangesPlugin(), | ||
| ], | ||
| options={ | ||
| "enum_prefix": "", |
There was a problem hiding this comment.
can you add a comment what this enum_prefix is for?
| uselist=True, | ||
| passive_deletes=True, # rely on PostgreSQL ON DELETE CASCADE to remove association rows | ||
| ) | ||
| ) # deletion cascade of generation |
There was a problem hiding this comment.
I don't know enough about the deletion, and cascade behavior that we want to be able to evaluate the correctness of this - I will leave that to @eleftherioszisis.
| if issubclass(mapper.class_, MeasurableEntityMixin) | ||
| and issubclass(mapper.class_, Entity) | ||
| and mapper.class_.__tablename__ | ||
| and getattr(mapper.class_, "__tablename__", None) |
There was a problem hiding this comment.
is this to skip the versioned table? Or something else?
| resource_route: ResourceRoute, | ||
| resource_id: uuid.UUID, | ||
| ) -> int: | ||
| """Return the number fo versions.""" |
There was a problem hiding this comment.
| """Return the number fo versions.""" | |
| """Return the number of versions.""" |
| base_query = constrain_to_accessible_entities( | ||
| base_query, project_id=user_context.project_id, db_model_class=id_model_class | ||
| ) | ||
| if version_num < 0: |
| libpq-dev \ | ||
| ca-certificates | ||
| ca-certificates \ | ||
| git |
There was a problem hiding this comment.
this is for convenience, right? not something to do w/ versioning?
| EntityType[mapper.class_.__tablename__]: mapper.class_ | ||
| for mapper in Base.registry.mappers | ||
| if hasattr(EntityType, mapper.class_.__tablename__) | ||
| if getattr(mapper.class_, "__tablename__", None) in EntityType |
There was a problem hiding this comment.
Was this change a result of some corner case? It would be nice to have a comment of the reason if this is the case.
|
|
||
| # If polymorphic_identity is different from __tablename__, it's a subclass | ||
| return mapper_args["polymorphic_identity"] != mapper_class.__tablename__ | ||
| return mapper_args["polymorphic_identity"] != getattr(mapper_class, "__tablename__", None) |
There was a problem hiding this comment.
Would it worth to create little helper funcs with docstrings to make these more readable?
| # are executed before the response is sent back to the client. | ||
| SessionDep = Annotated[Session, Depends(get_db, scope="function")] | ||
| PlainSessionDep = Annotated[Session, Depends(get_db, scope="function")] | ||
| SessionDep = Annotated[Session, Depends(get_db_with_user_context, scope="function")] |
There was a problem hiding this comment.
Maybe UserSessionDep?
This PR adds auditing/versioning using an external library sqlalchemy-history (fork of sqlalchemy-continuum).
Only sqlalchemy-continuum would support native_versioning (faster, using potgresql triggers), but the defined triggers have some limitations with polymorphism (they don't create a version of all the tables, and they don't set transaction_end on the previous version), so they would require some changes.
To consider all the deletions through the sqlalchemy models, the ON DELETE CASCADE defined in the db schema have been removed and replaced with a corresponding relationship with cascade.
This is less efficient, especially when deleting entities with many children, but the deletion is not the usual case so it could be acceptable. We can also reconsider the use of triggers later.
The tests are a lot slower because we have twice the number of tables, and we truncate them after each test. Using rollback instead of truncate could improve the performance, but it requires some changes in the instantiation of the sessions during tests.
Alternatively, we can disable versioning during tests that don't check versioning, and truncate only the non-version tables.