msupply-foundation / notify Goto Github PK
View Code? Open in Web Editor NEW"Notify" a multi channel notification scheduling tool
License: GNU Affero General Public License v3.0
"Notify" a multi channel notification scheduling tool
License: GNU Affero General Public License v3.0
As a configurator, I want to be able to get a list of recipients via an SQL query.
This feature should be implemented as a Proof of concept, and something we can improve on an extend in future.
This is for testing/debugging purposes, we need a mechanism to get data into the system to trigger alerts, reset alarms or what ever is needed.
The diesel Json
type is only available when the postgres feature is enabled, but our repository db uses SQLite. So, we're storing the configuration_data as a string (and will parse the JSON later when we use it.) However, we don't currently have any validation on that JSON string when it comes in (not even that it does parse to valid JSON!) We probably should.
For as long as we can't store the JSON as the Json type, we probably should at least check the string is parsable. We could also have a parse method available by the different plugins, to validate that the configuration data is in the expected format for a notification of that kind?
Take the frontend code from HSH and/or open-mSupply and commit a stripped back version.
Things we don't need:
Things we do need:
We need a way to configure reusable email lists/Telegram groups/perhaps a mix of both (?) which can then be referenced as the destination(s) when configuring a new notification.
Could look a lot like HSH Supplier lists.
Newer rust versions throw this error
warning: private item shadows public glob re-export
--> repository/src/db_diesel/mod.rs:12:1
|
12 | mod notification_config;
Sometimes we there isn't enough context/info from just the log type and the included id. An optional description would be a helpful first step in fleshing out our audit logs, especially for logs like RecipientAddedToList
(include recipient name/id in the description)
We currently only support the first item of the sort input array anyway, let's get rid of the array and just accept one sort param. We're unlikely to need more complex sorting for this app anyway.
Some view like this when opening a notification config where the configuration data is unable to be parsed. Currently the form just renders empty, and there is a little error popup.
Could also disable the ok button.
Build a interface for working with telegram.
chatid
s based on querying data from telegram API.The UI needs a page where we list all recipients, and where you could update them.
We need to read data from postgres for cold chain. This might just be a special repository/repository type that allows for other queries and connections?
When setting up a notification we want some common backend components that we can use to save the configuration.
This might be more complex for some plugins in future, but this will be a good starting point
A table something like this...
NOTIFICATION_CONFIG {
TEXT id PK "UNIQUE NOT NULL"
TEXT title "NOT NULL"
TEXT plugin_type "NOT NULL (COLD_CHAIN/ETC)"
TEXT recipient_ids "(JSON?)"
TEXT recipient_list_ids "(JSON?)"
TEXT configuration_data "NOT NULL (JSON)"
}
Code to create & update configs
Querying can be a separate issue...
Currently service provider is used from within service context. This feature isn't really useful and create dependancy problems.
Per RnD day: f8d389e
See also open-mSupply: https://github.com/openmsupply/open-msupply/blob/ad7479dd6db52ef6f6f0bb5c1506abb29e78acd1/server/service/src/test_helpers.rs#L28
Currently, we are storing the recipient ids and recipient list ids for notification configs in the configuration_data
. However, as every notification config will have these fields, it should be on the base NotificationConfig.
These should probably be two new join tables (notification_config_recipient & notification_config_recipient_list). They could then be added to the NotificationConfigNode
via loaders in the graphql layer for the frontend.
Originally we thought to simply have recipientIds
and recipientListIds
as fields on the NotificationConfig, but this is a bit brittle (i.e. if a recipient is deleted, or what if we want to see that the notifications a recipient is subscribed to?) The join seems more robust/flexible.
If you are editing a recipient list, it would be nice to be able to quickly create a new recipient if the one you are looking for doesn't already exist...
On the Recipient list view...
Either
Add ability to send a test telegram message to a telegram recipient.
Some button on the recipient modal?
Right now it's really hard to test out a scheduled report to see if it works, it would be great if there's a way to
Add a new Test
button similar to the test query button on the Notification Query Page.
It should return a view with information such as.
Having a consistent approach to dealing with service errors, especially rare ones that may require different user actions is important.
TODO Link to Code Review comments once it's written...
Replace GenericError
with InternalError
or BadUserInput
as per usage.
Assume will do postgres to align with mSupply/grafana databases, but could still have sqlite a long side, this is what the grafana plugin does already?
Do we still need sqlite for testing (I assume Yes)
Do we have a separate connection string/setting for configuring postgres internal db vs ones it connects too to monitor?
You can use the tab key to tab through the Cold Chain notification toggle fields, but the enter key doesn't select them.
Steps to reproduce the behaviour:
The enter key selects/deselects the highlighted checkbox
If the title template is missing, or has a render error blank title could be rendered
` log::error!("Failed to render notification template: {:?}", e);`
Steps to reproduce the behaviour:
Take the backend code from HSH and/or open-mSupply and commit a stripped back version.
Things we don't need:
Things we do need:
Things I'd like to change:
As discussed with Andrei, having feature flags that aren't being used causes confusion to devs.
We should remove them. If we need to support postgres and sqlite in the future again we can always re-instate them.
Tera templates can be reloaded like this:
tera.full_reload()?;
https://tera.netlify.app/docs/#reloading
Would be awesome if we could either a trigger a reload from the UI, or automatically watch for changes to templates.
Ideally would do some kind of validation and only reload it the templates actually work???
You cannot delete a recipient if they are a part of a recipient list.
Steps to reproduce the behaviour:
No error - deleting a recipient should be possible, and they should no longer appear in the recipient list(s).
Either soft delete recipients, and then add an additional filter on recipient list members that the recipient isn't flagged as deleted, or delete all recipient list members for that recipient id - maybe one is better than the other for logging/transparency/etc?
Need a method for configuring datasources for notify to use.
Probably part of the main local.yaml
We want to display a nice alert in telegram when there is a temperature breach.
For this issue, we want to.
High temperature alert!
Facility: Store A
Location: Fridge 1
Sensor: E5:4G:D4:6D:A4
Date: 17 Jul 2023
Time: 17:04
Temperature: 10° C
//// ~ insert cute graph here ~ ////
In future we'll have other kinds of alerts and data, so we should consider this while coding but hard code if fine for now.
There is a many to many relationship between both NotificationConfig and Recipient, and NotificationConfig and RecipientList. However, when it comes to sending the notification, we don't really care about the recipient lists, we just want to know who to send the notification to.
Would be great to have some kind of get_all_recipients_for_notification_config
in the service layer, that resolves all the recipient ids for any selected recipient lists, and joins these will the selected recipient ids.
It's probably fine just to return all the ids? And let the notification sending code query any extra required information?
A cold chain alert should be possible to setup with a simple form.
Each alert will apply to a group of stores, locations, or sensors.
The user should be able to select a store and all the locations and sensor underneath would be automatically included.
(similar for a location)
Each notification will apply to one group of stores/sensors/etc and any notification groups included will be notified with the same data.
Note: If we want separate alerts for different stores, we'll need to setup multiple notifications/alerts.
Ideally this would be configured with a JSONForm so conceptually it's generic.
however if we have to hard code so be it.
Managing how to actually store and process the data will be a separate issue.
[2023-08-10T23:44:23Z ERROR telegram::service] Error parsing update: Error("missing field title
", line: 0, column: 0) update: Object({"message": Object({"chat": Object({"first_name": String("James"), "id": Number(5068627745), "last_name": String("Brunskill"), "type": String("private")}), "date": Number(1691711063), "entities": Array([Object({"length": Number(6), "offset": Number(0), "type": String("bot_command")})]), "from": Object({"first_name": String("James"), "id": Number(5068627745), "is_bot": Bool(false), "language_code": String("en"), "last_name": String("Brunskill")}), "message_id": Number(77), "text": String("/start")}), "update_id": Number(794348098)})
Steps to reproduce the behaviour:
Chat Id should be recorded but with users name?
In PR #20
Similar to health supply hub, build scripts that can be called from a github webhook.
Create a mock up for scheduled report config.
Create a mermaid diagram with a database structure in the docs folder.
Given there is a many-many join table for the relationships between notification configs and their recipients/recipients lists, you currently get a foreign key constraint violation if you try to delete a notification config while has recipients, or a recipient list while it is associated with a notification config.
Recipients have soft deleted implemented on them, we also need it on RecipientLists and NotificationConfigs.
Steps to reproduce the behaviour:
Add a recipient list to a notification config.
No errors, delete (softly) the entities
running 3 tests
test tests::test_select_with_with ... FAILED
test tests::test_invalid_query ... FAILED
test tests::test_simple_select ... FAILED
failures:
---- tests::test_select_with_with stdout ----
thread 'tests::test_select_with_with' panicked at 'the DATABASE_URL environment variable must be set: NotPresent', datasource/src/lib.rs:66:38
---- tests::test_invalid_query stdout ----
thread 'tests::test_invalid_query' panicked at 'the DATABASE_URL environment variable must be set: NotPresent', datasource/src/lib.rs:87:38
note: run with RUST_BACKTRACE=1
environment variable to display a backtrace
---- tests::test_simple_select stdout ----
thread 'tests::test_simple_select' panicked at 'the DATABASE_URL environment variable must be set: NotPresent', datasource/src/lib.rs:43:38
Steps to reproduce the behaviour:
Should be able to run default tests without errors. Maybe a default postgres config, feature flag or similar?
Database design for notification groups
If a notification can't be sent with a temporary error, we should retry sending, but should wait longer between each attempt.
Suggest something like
We could have more attempts and/or change the logic abit, I'm not too precious about it.
I think anything that can't be sent say with in 12 hours definitely shouldn't be sent, but maybe we should try again within 2-4 hours?
When setting up a recipient list with an SQL Query, you want to be able to test that your query works.
We also want to be able to use the results of a query when creating a notification.
We want graphql request that returns a list of Recipient Rows based on an SQL query (in future possible a template and params?)
Server should throw an error if the query results can't be mapped to a list of recipients
Hopefully error type can contain the json received from the DB so we can investigate/understand what's not matching, and/or good error messages.
Keep what we have in PR #97
Running a query for the bot name, query results should be in the following format:
{
"status":"success",
"isLoading":false,
"isSuccess":true, // if true, error is null and data populated
"isError":false, // if true, data is null and error populated
"data":"some-botname",
"error": null,
...
}
However, if there is an error getting the botname, it still "succeeds" and sets the error message as the data.
{
"status":"success",
"isLoading":false,
"isSuccess":true,
"isError":false,
"data":"Unable to get botname : Temporary(TimedOut(\"error sending request for url (https://api.telegram.org/bot6374528256:AAGgjZaS_6qnrtZFDGRtu6fFiOsaEiClNSI/getMyName): operation timed out\"))",
// or "data": "Telegram service not configured"
"error": null,
...
}
Steps to reproduce the behaviour:
botName to be null, with an explanatory error message as to why it is unavailable. We aren't always wanting to throw (bot may not be configured, that is okay)... maybe the success return type could be something like:
{
name: String | null
reason: String | null
}
If there is an actual error, it should come through as an error though?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.