Atomically move redis key on expiration - lua

Is there a way to atomically move a redis key from one place to another when it expires? There's ways of doing this in the client by being notified of redis expire notifications, but if no clients are running when the notification is triggered then the event is missed.
But if there's a way to do it on the server (through a LUA script maybe) then it can be atomic and the key exists in one place before the expiry and the other place after expiry.

Expiration keyspace notification isn't fired when the key expires. It's not guaranteed to happen as you might expect... (see Timing of expired events)
When the key is accessed by a command and is found to be expired.
Via a background system that looks for expired keys in background, incrementally, in order to be able to also collect keys that are never
accessed.
IMHO, I believe that you should go with another approach. Use some external task scheduler and automatically start a task to move expired keys some seconds or minutes before they're going to get expired. I understand that you'll check if target keys are still alive using ttl command.
For me, key expiration is a good approach to automatically free up memory but you shouldn't use it to produce actions based on expiration events since it's unreliable for such use cases.

Lua scripts cannot be triggered by a keyspace notification.
You must do this on client side.

Related

Apple Push Notifications from a serverless MongoDB App Services backend

I have been setting up Apple Push Notifications for an iOS app, using JSON Web Tokens rather than certificates.
I can generate a JWT and make the required POST request from within the app (using the Swift-JWT package) and the notification is delivered.
I am using MongoDB Realm, which has serverless functions (in JavaScript with a Node environment) that are called from the iOS app. A scheduled trigger updates my JWT, as Apple advise it should be refreshed every hour.
However, despite trying several Node modules for making the POST request there were always errors (like “BadDeviceToken” or “InvalidProviderToken”).
I finally got it working using the node-apn package! However, I have two queries about using it in this serverless function context:
It tries to keep a connection open to the Apple server, which would be fine, except it might mean a new connection is opened every time the function is called. Calling Provider.shutdown() does not seem to stop the connection. I don’t think I can have a long-running process to receive future requests in a serverless context.
Apple advise not refreshing the JWT more often than every 20 minutes. node-apn manages the JWT for you, but in a serverless context, will it be generating a new token every time the function is called? Notifications do seem to get delivered every time I test it in development mode (to the Apple sandbox endpoint).
I’d be grateful for clarity on these points, and whether node-apn is appropriate to use in serverless functions.
Update
Provider.shutdown() not working seems to be a recognised issue.
I was able to shut down using this workaround:
Provider.client.endpointManager._endpoints.forEach(endpoint => endpoint.destroy());
I would still like to know about whether it is reasonable for this to be used in a serverless function. I am concerned about JWT being refreshed with every request, which Apple may not like!
I have scanned through Apple's documentation on this and given some thought to your question about refreshing tokens within a serverless context.
You could imagine the following approach for ensuring that you refresh the token no more than once every 20 minutes and at least once every hour, as per Apple's documentation:
Generate the token for sending a single notification request
Send the notification, and then after, in the background, save that token to some collection (e.g apn_tokens) inside of MongoDB (optionally alongside a createdAt timestamp field)
On the next request to send a push notifcation, fetch the stored JWT token from your server.
If the token's createdAt date (or iat field on the JWT itself) is less than an hour (or within some threshold less than the hour e.g 50 mins), then reuse the token in sending the push notification request
Otherwise, restart the process from step 1!
Note on this process: It would require that your database (or theapn_tokens collection) is only accessible from trusted sources (i.e your cloud application/functions alone), if they aren't already. Clients should not have access to this table in any way. You can imagine setting Collection-Level Access Control for your serverless environment. As an extra layer of security, you could imagine deleting "expired" tokens after re-generation in step 1, such that there is only one token present in the table at any time in order to prevent potentially active tokens from laying around in the database without use.
I hope this helps!

Service worker update period

I'm creating a simple web app that can connect to a bluetooth device that I want to be able to use offline, so I use a service worker to store the app in the web cache. I know the cache only clears if there is no more space but what about the service worker?
I found that is lifespan is 24 hours. My question is how long can I use the web app without connecting to the internet? Is the cache the only problem or does the service worker "die" after x amount of time and I need to connect to the internet again?
No, it does not die. You can use it forever.
You're confusing two things. The 24 hour lifespan is actually an automatic update checking interval. In other words, when using a site frequently the browser will automatically check for updated Service Workers (specifically updated /serviceworker.js or wherever you store it). Your code can of course manually, programmatically check for SW updates more often. Usually apps check for new SWs every time they're launched. But the device may be offline for eg a month and that doesn't prevent the use of the app.

Objective-C - How to prevent session id reusing when app terminated?

My main question is how to detect the application termination by the end user when it was in the background (Suspended) to be able to send logout request to the server ?
We already have a timeout interval in the server to kill the session, but assume that the interval is 5 minutes so this means that the session will be alive for 5 minutes after the user terminated the app and anyone can sniff on the data and reuse it.
Notes:
We use HTTPS connection and SSL Certificate Pining.
We also implemented a heartbeat web service to be called by client app every fixed interval to tell the server to keep the session alive for this interval, if this web service didn't call for specific session, the server will kill this session.
Once your app is suspended you don't get any further notice before you are terminated. There is no way to do what you want.
Plus, the user could suspend your app to do something else (like play a game) and then not go back to your app for DAYS.
If you want to log out when the user leaves your app, do it on the willBeSuspended message. Ask for more background time and send a logout right then and there.
Mohamed Amer,
Here is an approach used by Quickblox Server and I feel its pretty much solid though it involves a little overhead.
Once the client application (either iOS android) establishes the session with quickblox server, quickblox server expects the client application to send the presence information to server after a regular interval continuously.
Sending the presense information is pretty much simple. They have written a api which we keep hitting after a interval of 5 mins with session id that we have. They validate the session id and once found valid they will extend the expiration time for the user ascociated with that id for 5 mins more.
What they will do I believe is that,
Approach 1 : they maintain the last hit time and for all the subsequesnt request they check if the request time is within the the time frame of 5 min if yes simply process it. If the request comes after 5 min they will delete the session id for the user and respond saying you have timeout the session.
Approach 2 : Because they provide online and offline info as well they cant simply depend on the incoming request to delete the session id from server so they probably create a background thread which swipes over the db to find the entry with last hit time greater then 5 min and removes it from DB. and declares the user session expired.
Though this involves client apps continously hitting the server and increases the burden on the server for the app like chat application in which presense information is so vital this overhead is still fine i believe.
Hope I have provided you with some idea at least :)

Swift wait for existing async operation to finish before starting a new one

I'm working on a Swift project that uses token based authentication. When the application resumes from the background the the AppDelegate function applicationWillEnterForeground() does a check to make sure the token in memory hasn't expired (expiry date is stored in NSUserDefaults and in the token_expiry variable). If it has expired, it'll call a function to renew and get a new one.
The problem i'm facing is that while the async function is waiting for the server to reply with a new token, the user in the app could do something which requires authorisation. If this happens, since a new token has not been acquired yet the app will query the server using the old token value and data will not be retrieved.
Is there a way to ensure that the async function to renew the token has finished before we do anything else?
Set up a system of NSNotifications to inform your GUI when authentication is valid/invalid.
In your GUI, enable or disable the user controls that need authentication as appropriate when the notifications occur. How you do this will depend on your GUI design: hiding controls, greying out controls and activity indicators are some options.
Send these notifications as appropriate when you check authentication.

Best way to notify iOS app on server database updates

I am quite new into programming and I cant find efficient solution for my problem. Could someone point me in the right direction please?
I have an app which is heavily relying on server data. Data on server is unique for each user and may change every minute as well as only every few hours. Currently I am updating local data when app becomes active but I also need a way of notifying app to trigger updates when app stays in active state and data has changed on server. I thought about few solutions:
1) NSTimer set to one minute and triggering url request to check if there is new data on server. Server after comparing lastModified value would return new data if available.
I don't really like that solution as I don't want to overload my server with number of requests, especially that data in the database may change only every few hours or even longer.
2) APNS - sending notifications from server every time data will change and than update local data with server database when notification received.
It seems like a good solution but only if it would be possible to restrict remote notifications to be received when app is in active state. As far I know it is not possible and as I mentioned before data may change even every minute so I don't want to spam users with number of notifications when app is not running.
3) TCP Sockets using NSStream/CFStream?
This is something I never did before, so I am not even sure if I am going in the right direction researching about this one.
This is a hard topic in general, but more technologies are coming out to help with it. Couple thoughts on each of your solutions:
The NSTimer solution is effectively polling, which is the worst option I feel. You'd be hitting your server pretty hard for each user.
This would be a better solution. APNS now supports silent notifications, so you can send push notifications to a user without worrying about notifying them. You can send a silent notification by including the content-available key in the payload and not including the alert key. More info here: http://hayageek.com/ios-silent-push-notifications/. It is rate limited, though. You may go minutes to hours without getting a delivery, so if that's important you'd be best to go to option 3.
This is your best solution. It would require a persistent connection with your server. AFNetworking 2.0 supports this kind of connection based on Rocket. Here's Rocket's documentation: http://rocket.github.io. Take a look at server-sent events.
Hope that helps!

Resources