Data based push creation/deletion

5 posts, 0 answers
  1. Phil
    Phil avatar
    15 posts
    Member since:
    Oct 2012

    Posted 27 Jan 2015 Link to this post

    I've been going around in circles today trying to figure out the best approach, but I'm still lost. Hoping someone here has the answer.

    My user has a group of records with dates. I need to send a single push notification to the user for each unique date in that data.

    I can create this push notification on the client side when a record is created. However,the client sdk for notifications only exposes create, not read or delete. That means -

    1. I can't make sure there's only one notification per device, even if there are multiple records with the same date.
    2. I can't change/remove the existing push notification if the date in a record is changed.

    I thought about using Cloud Code for Data... But the sdk doesn't expose read/delete. I'd have to read all notifications for that User Id from the REST service and then determine which need to be updated/removed. That sounds like a mess of code for a scenario which I would consider somewhat normal. I'm also concerned about timing out, since there's a 5 second limit on cloud code for data.

    So, what's the best way to manage my push notifications?
  2. Anton Dobrev
    Admin
    Anton Dobrev avatar
    539 posts

    Posted 28 Jan 2015 Link to this post

    Hi Phil,

    Thank you for posting to the Telerik Developer Forums.

    You can read the created notifications from the REST API as explained here.

    You can retrieve the notifications in the Cloud Code/Cloud Functions with a similar code:
    var data = Everlive.Sdk.withMasterKey().data('Push/Notifications');
     
    var filter = {};
    data.get(filter, function(data) {
        var notificationsArray = data.result;
        done();
    }, function(err) {
        // handler the error here
        done();
    });

    In addition:

    • You can Update an existing notification object by its Id if the notification is not yet sent (e.g. scheduled for delivery in a future moment in time). If the notification is already sent, you cannot update it and you will receive an error result.
    • You can Delete a notification by its Id (if the notification is scheduled - deleting it will remove the scheduled task for its delivery, but not the existing object). 

    Please note:

    • Reading and Writing an existing notification requires Master Key authentication. Do not expose the master key for your backend project in the client app or to third parties.
    • The time for querying existing push notifications will raise exponentially with the amount of existing push notifications objects your are looking up with the query. This might result in a timeout in the cloud code, however, the timeout limit is sufficient to make a query to a reasonable amount of items.

    Based on the information you provided, I'd suggest that you consider to schedule a notification for a current date (using the NotificationDate property in the payload) and user. Update the notification when needed. If the notification cannot be updated (e.g. it is already sent), schedule a new notification.

    Let me know if this helps and if you have questions.

    Best regards,

    Anton Dobrev
    Telerik
     
    Everlive is now Telerik Backend Services, and is part of the Telerik Platform.
     
  3. Phil
    Phil avatar
    15 posts
    Member since:
    Oct 2012

    Posted 29 Jan 2015 in reply to Anton Dobrev Link to this post

    Thanks Anton, that helps a lot!

    Can you give me the names ans signatures of the methods for update/delete of push notifications? I have pored over the documentation all day and cannot find them anywhere. 

    I've tried deleting like other data with a filter -
    var pushes = Everlive.Sdk.withMasterKey().data('Push/Notifications');
    var pushdelquery = new Everlive.Sdk.Query();
    pushdelquery.where()
        .regex('Filter', JSON.stringify({"UserId": userid}), 'i')
    pushes.destroy(pushdelquery)
        .then(function() {
            //success
        },
        function(error) {
            //fail
        });


    Like deleting single data like this -
    var pushes = Everlive.Sdk.withMasterKey().data('Push/Notifications');
    pushes.destroySingle({ Id: pushid }, success, fail);

    And finally, I started hacking around just trying to guess how it works with code like this -
    Everlive.Sdk.withMasterKey().push.notifications.delete(pushid,
            function(error, response) {
            if (error){
                //return error here
            } else {
                //return success here
            }
    });

    Nothing is working. I would appreciate your assistance on this one.

    Thanks,
    Phil
  4. Anton Dobrev
    Admin
    Anton Dobrev avatar
    539 posts

    Posted 30 Jan 2015 Link to this post

    Hello Phil,

     Currently you can delete a notification only by its Id (e.g. DeleteAll and DeleteByFilter operations are not allowed). For instance:

    Everlive.CloudFunction.onRequest(function(request, response, done) {
        var pushes = Everlive.Sdk.withMasterKey().data('Push/Notifications');
     
        pushes.destroySingle({
                "Id": "ed72c800-a875-11e4-9a89-41765a9e8810"
            })
            .then(function(data) {
                    //success
                    console.log(JSON.stringify(data));
                    done();
                },
                function(error) {
                    console.log(JSON.stringify(error));
                    done();
                });
    });

    I do apologize if my previous reply was not enough clear on the matter.

    Let me know if you have questions.

    Best regards,
    Anton Dobrev
    Telerik
     
    Everlive is now Telerik Backend Services, and is part of the Telerik Platform.
     
  5. Lyubomir Dokov
    Admin
    Lyubomir Dokov avatar
    43 posts

    Posted 03 Feb 2015 Link to this post

    Hello Phil,

    This is a follow up on our phone call yesterday.

    I would like to propose you a simpler way to achieve what you need and I also have some suggestions on optimization of your cloud code.


    First, the simpler solution.

    Scenario:
    You have a database of Contacts, each Contact has a field that specifies when this Contact must be contacted again(follow up on a deal or whatever) - NextContactDate. You want to remind the users of the mobile app that they need to contact certain Contacts using push notifications. However, you want just a single push notification per day, not a notification for each Contact that must be contacted on that day.

    Your current solution:
    Whenever you create or update a contact, you check if there is a notification for the date in NextContactDate. If no, you create the notification. Also, on update and delete you also check if the original NextContactDate (before the update) has no contacts left for it. If yes, you delete the push notification for that date, because you no longer need to remind for anything on that day.

    Proposed solution:
    I would like to propose a more simple solution that will work the same, but will be more easily manageable and will be more straightforward.
    I suggest that you do nothing in the Contacts cloud code. Instead, create a cloud function that runs once a day (more on that later). In this cloud function you read all contacts with NextContactDate equal to today. If you get any contacts - you send a push notification. If not - you do nothing. I believe this way you will get the same functionality, but with much less code and efforts.
    So, the question is how to make the function run once a day? We do not support this out of the box right now, but it is still very simple. Executing a cloud function is just an HTTP request to a special URL. There are various services that can do that for you on interval - https://uptimerobot.com, https://www.setcronjob.com, https://www.easycron.com, https://www.site24x7.com or similar. If you happen to have some kind of server of your own, you can easily set it up there as well.

    Let me know if the proposed solution works for your case. I think it would be much more simple to only create notification once when you are certain you need it, instead of creating it always and then deleting it in case it is not needed.


    Second, some Cloud Code advises:

    • Empty event subscriptions - please avoid having empty event subscriptions, where you subscribe for some event and the only thing you do inside your handler is call done(). This seems harmless but actually decreases performance. We cannot tell if you have any real code in your handler, so we execute it anyway. If you simply do not subscribe for the event nothing is executed. Example for an empty handler in your code is this:
    • Everlive.Events.afterRead(function (request, response, context, done) {
          done();
      });
    • Calling done() without return - I saw a couple of places where you call done() without having return at the same time. Calling done signals us that you finished your execution and we start to gather the results and then kill the code execution process. However, if you have some code after done, it might get executed if you do not have a return as well. Here is an example:
    • Everlive.Events.afterUpdate(function (request, response, context, done) {
          if (!context.contactDateChanged) {
              done(); //nothing to do, date didn't change
       
              //NOTE: execution continues here even if you call done(). Instead, do this:
              //return done();
          }
          
          var contact = request.data.$set;
          contact.Owner = context.owner;
          contact.Id = context.contactId;
          updatePushes(context, contact, done, true);
      });


    Once again, thank you for your feedback and for taking the time to discuss everything with us on the phone yesterday. I am leading the engineering in Telerik Backend Services and this input is really valuable to me and the whole team.

    I hope my suggestions will help you get where you need. Let me know if you have any questions.


    Regards,
    Lyubomir Dokov
    Telerik
     
    Everlive is now Telerik Backend Services, and is part of the Telerik Platform.
     
Back to Top