moigagoo / norm

A Nim ORM for SQLite and Postgres
https://norm.nim.town
MIT License
384 stars 34 forks source link

[FeatureRequest] Adding Hooks/Signals for post/pre insert/delete/update operations? #131

Open PhilippMDoerner opened 2 years ago

PhilippMDoerner commented 2 years ago

I have a webapplication with a Django backend that I am currently rewriting in nim using prologue and norm.

Django has a pretty neat signal system that allows you to run defined code before or after a data-manipulation-action such as insert, delete or update happens. In fact, I am implementing such a thing at the moment in my own side-project, because I made quite some use of it in my previous backend which was written in Django. In my case though, they are more "hooks" that you can use, rather than a proper signalling system.

The key idea of the implementation would be, to have pre-defined proc signatures that the user of norm can define and if they do define them, they are run. If they don't define them, that works just as well. For an example, I shall refer to my sideproject (that is my abstraction layer between my application and norm. See the procs createEntry, deleteEntry and updateEntry).

Since the code calling for such signal/hook procs is compiled away if they're not present, there would be no impact on performance by adding such a feature.

I can look into a norm-implementation of such a thing and submit a PR as I did for #127 , but I thought it might make sense to first even ask if such a feature is desired or if you see problems with it before I waste time on something unwanted.

PhilippMDoerner commented 2 years ago

@moigagoo Is this feature something you would accept to be in norm? It's very much just arbitrary procs that the user can "attach" to a given model and for a given trigger moment (before or after create/update/delete) as an automatism. An example usecase would be if you had an sqlite fts5 table and immediately after creation/update/deletion wanted to modify said entry in the search-table.

I'm pretty much using something like it already for exactly the usecase above. It consists of one signalSystem.nim module to store a global Table STORE of pointers to procs with a proc(dbConn: DbConn, entry: Model) like signature. These are mapped to model types and then in my generic repository that abstracts norm away, I call "triggerSignal" before and after doing a create/update/delete operation. If a proc for the given model type exists, it is then executed.

The signalModule can be looked at here: https://github.com/PhilippMDoerner/NimStoryFont/blob/master/src/applications/core/signalSystem.nim

Examples on how I use them: 1) Updating an FTS5-Search table when an entry whose content is reflected in that search table gets updated: https://github.com/PhilippMDoerner/NimStoryFont/blob/master/src/applications/search/searchSignals.nim 2) Creating permissions and groups for accessing a specific campaign when a new dnd campaign has been created (The interesting part starts at line 63): https://github.com/PhilippMDoerner/NimStoryFont/blob/master/src/applications/campaign/campaignSignals.nim

For norm I'd write something up based on the signalSystem.nim module and add 2 triggerSignal calls per proc to insert (sqlite.nim line 164 + 166), `update (sqlite.nim , lines 290 + 292) and delete (sqlite.nim, lines 307 + 309) in the sqlite.nim and postgres.nim modules.

Before I start adapting the above I'd want a statement as to whether that effort is even desired or not though.

curioussavage commented 1 year ago

I would also like hooks for all operations, but for implementing telemetry.