MongoDB, Mongoose delete element after x time and receive event - mongodb

I have an expressjs api which uses mongoose to manage the MongoDB. Now I have a document called notifications, some users receive notifications when some conditions are met, e.g. new item(s) are available for the user. The notifications are only sent in x time (stored in user settings) and every user can have max 1 notification in the notification collection. After a notification is sent it is deleted.
I can ofcourse retrieve every x time all user settings of users that have a notification. And then check (time comparison) which users can be notified now.
I would like to delete a notification after x time and then receive a delete event, and then I can send a notification based on that event.

What I did was to create another collection e.g. NotificationTtl. A NotificationTtl is only created when a Notification is created, with the ttl set to the correctly based on the user settings.
We make another collection because it is better not to delete the notification before it has been sent. We can add a field with notificaiton_id, but because every notification has one notificationttl we can give the notificationttl the same id as the notification.
var NotificationTtlSchema = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})
var NotificationTtl = mongoose.model('NotificationTtl', NotificationTtlSchema);
NotificationTtl.watch().
on('change', data => {
//this will be called ever time create/update/delete executes here we can listen for delete
});
In the watch we can then listen for a delete operation if the delete operation has been executed we can get the id of the notificationttl and with that id we can retrieve the notification and send it, after it has been send we can delete it.
This all works only if the mongodb is a replicaset and a master node, else the watch functionality wont work.
So what happens now is that everytime the notifiction ttl expires I will get an event in my watch. The event will have operationType called delete, I will then retrieve the correct notification and send it to the user.

Related

Is there any way to get deleted row data from smartsheet using webhooks

To notify the events on smartsheet, I have created a webhook. Using I am able to get all events performing on sheet. If I delete a record manually, I am getting the deleted event with rowid, but not the total deleted row data. Is there any way to get the deleted row data?
Thanking you in advance
The callbacks that you receive via webhooks are simply intended to notify you when events occur -- i.e., by design, each callback contains only enough data to identify the event that triggered the callback.
Update 10/19/2020:
Unfortunately, you won't be able to use the Get Row operation to retrieve data for row after it's been deleted. Therefore, seems like you'd need to somehow write/save sheet data elsewhere as the sheet is modified (e.g., perhaps in response to webhook notifications that indicate row data was added/modified?), then you could query this saved sheet data to get row data as rows that are deleted from the actual sheet (i.e., in response to 'row deleted' webhook notifications).

RESVT Bulk Update

I had a question last month about POSTing to Workfront's RESVT field. Since then, I've completed my database to pull all of our department's Leave Calendar data and feed it into Workfront's API as POST methods; however, I've discovered a new problem.
Every time I add a new RESVT event to a user with an existing RESVT event, it deletes the previous event before it saves the new event. I've looked into submitting a bulk edit using the bulk editing format to get all of the events for a user online all at once like this:
https://sosprojects.preview.workfront.com/attask/api/v9.0
/5b6b72b5007d93b00b00dda361398cad?method=put&updates=
[
{
objCode:”RESVT”,
startDate:”2018-08-20T00:00:00:000-0700”,
endDate:”2018-08-23T00:00:00:000-700”
},
{
objCode:”RESVT”,
startDate:”2018-09-20T00:00:00:000-0700”,
endDate:”2018-09-23T00:00:00:000-0700”
}
]
&sessionID=209055d209f94662b32ac50175b34bc7
Which Workfront "accepts" (it doesn't spit out an error code), but it still only saves the last RESVT event (e.g. 9/20 - 9/23).
I've tried using PUT to edit an existing RESVT event, but each RESVT event will only accept one start and one end date so it collapses those attempts into one extra long event.
I know the time-off calendar can manually create multiple RESVT events per user, but I can't figure out how to replicate that feat with my http methods. The calendar always creates new RESVT events for every event logged whenever I add a new event to it; so I think it is doing something like the bulk POST I tried at the top, so why can't my method do the same thing?
The API docs don't show update as a valid method for the RESVT object. Just modify the fields directly for the specific object you want to update. Do you know its ID?
PUT https://<url>.my.workfront.com/attask/api/v9.0/RESVT/<ID of the reserved time you want to edit>?userID=abc1234,startDate=<date>,endDate=<date>

How to manage Daily Bonus push notification with One Signal?

We have a daily bonus system working on date basis. Every date in your local time, you have right to take 1 daily bonus. Ex: If you get daily bonus on 12 July, you will get right to take next bonus on date 13 July without depending on time.
I would like to create push notification for users, but i could not sort it out how to do it?
My previous tries:
1- Whenever player gets daily bonus, i tried to create notification for the next day at 8 pm in her local time.
Problem: If player takes bonus on the next day before 8 pm, i could not delete previously created notification, because there is no delete function for Unity. I also tried collapse_id to deal with it, but collapse_id do not stop sending the notification, just updates notification info with the last one when it is received.
2- I created a tag which is the date when bonus collected, it is something like "2018-07-12". I tried creating a user group who compares these tag with the "today's date"
Problem: there is no such thing like todays date you had to enter it as value, so you can do this by entering console changing date and sending notification and you need to do it everyday.
How can I create such notification system?
Thanks.
Hasan
There are 2 options to do this with OneSignal.
1 - You can cancel the notification if the user already took the bonus.
You can use something like this to make the cancel request:
string url = ""https://onesignal.com/api/v1/notifications/"" + notificationId.ToString() + ""?app_id="" + s_appId;
WebRequest request = WebRequest.Create(url);
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
request.Method = ""DELETE"";
request.GetResponse();
2 - If you are tracking this on your own CRM or database, then you can save the OneSignal PlayerID to the database and target device with the API.
First, get the playerID with the SDK: https://documentation.onesignal.com/docs/unity-sdk#section--getpermissionsubscriptionstate-
Then you can send this data to your CRM or database: https://documentation.onesignal.com/docs/internal-database-crm
​
You can then use include_player_ids on the create notification REST API POST call https://documentation.onesignal.com/reference#section-send-to-specific-devices
If you want to go the tagging option, you should use a timestamp and then target with the API and filters https://documentation.onesignal.com/reference#section-send-to-users-based-on-filters
You should never put your OneSignal REST API key within your app. This needs to be kept private.

lazy loading meteor subscription

Say I subscribe 10 documents when the page is rendered and subscribe more documents as and when needed. Basically I am showing images to the user. So when the page is opened, I want to subscribe the first 5 documents. Now when the user is on 3rd document, I want to subscribe the next 5. Any help on how to proceed??
I can subscribe to the first 10 documents using limit property of mongodb. I know when to fire the next meteor.subscribe call but how should I mention that it should subscribe the next five documents
A simple pattern to do this is to use a Session variable or a reactiveVar to track how many items you want to load then have a Tracker.autorun() update the subscription automatically when that changes.
Initialize (when you're setting up the layout):
Session.set('nDocs',10);
Tracker:
Tracker.autorun(() => {
Meteor.subscribe('myPublication', Session.get('nDocs'));
});
Event Handler (triggered when the user views the 3rd doc in your case):
someEvent(ev){
Session.set('nDocs', Session.get('nDocs')+10);
}

Sails js with socket io: how to subscribe to new Model that fits criteria, during onCreate?

I am using Sails js 0.11.
Following the tutorial described on the docs here:
I am able to create a pub/sub relationship. However I only want to be notified of "update" events of users that have the field "company=abc". Therefore in the controller I do the following:
subscribe: function(req, res) {
User.find({company:'abc"}).exec(function(e,listOfUsers){
User.subscribe(req.socket,listOfUsers,['create','destroy']);
});
}
This works. However in the case this socket is open, and a new user belonging to this company is created, the socket won't receive notifications for this new user.
In order to solve that, I went to User model, and added:
beforeCreate: function(user, next) {
//just need one sample of user from this company.
//in theory all users of this company are subscribed by same sockets
User.findOne({company:user.company}).exec(function(e,companyUser){
// Get all of the sockets that are subscribed to this user
var subscribers = User.subscribers(companyUser);
// Subscribe them all to this new user
_.each(subscribers, function(subscriber) {
User.subscribe(subscriber.id, user);
});
next();
});
}
However I get the warning
warn: `Model.subscribe()` called by a non-socket request. Only requests originating from a connected socket may be subscribed. Ignoring...
I do not want to create user using sockets. Is there a way around this? Just want to keep my socket subscribers up to date!
Thanks
Actually, putting this in the afterCreate won't really work because the subscriber would receive the message when the object created, but you are putting this after its being created so the event won't run.
However with a trick, we can make this work. Subscribe to the Company instead of the User, here are the details:
So first, subscribe your user to it's company (owner is the company id in my sails app):
Company.findOne({id: req.session.user.owner}).exec(function(e, company) {
Company.subscribe(req.socket, company);
});
Then when you create a User, in the afterCreate, look for the company id in your socket message. Retrieve all of the subscribers of that company, and subscribe them to the "message" context of a User model. Then right after you subscribed all of your user's send a "message" type message to them via the Company model's message() function.
afterCreate: function(message, next) {
Company.findOne({id: message.owner}).exec(function(e, company) {
var subscribers = Company.subscribers(company);
_.each(subscribers, function(subscriber) {
User.subscribe(subscriber, message, 'message');
});
Company.message(company, message.message);
});
next();
},
Here, the message object is the socket.io payload. In the first section where you subscribe your socket client to the company, you can have criteria to specify which user's to subscribe to where, even you can create a specific subscribers criteria table where you store all the different subscription channels.
Hope it helps.
References:
http://sailsjs.org/documentation/reference/web-sockets/resourceful-pub-sub/subscribe
http://sailsjs.org/documentation/reference/web-sockets/resourceful-pub-sub/message