I'm working on an app a little like Vine, where several looped videos are displayed on the screen of the user. I need to count one view per loop. It means, if the user repeat the video 5 times, it will count 5 views. And this is the model I want to use for every videos of my app.
I use Parse for my back-end and a webview to show the videos. It means that I use Javascript to send requests to Parse, with Ajax calls.
My problem is that I don't really know how to limit the number of requests sent to Parse when I add a view on a video.
Maybe I should save the video views to a MySQL database and then, once a day with a cron task, save the MySQL results to Parse? I don't really know how to proceed, but I really need to limit the number of requests to Parse.
How would you design this?
Thanks!
My first thought is to not optimize too early. There should be plenty of time, as you accrue zillions of users, to improve the design.
If you want to improve it early (and still use parse), keep the object that tracks views "pinned" locally (see this blog entry). Update the view count as often as needed, then update parse on an NSTimer.
The app may become inactive at any time, and if unsaved views have been counted since last time the timer fired, then there's one more problem to solve. The app delegate gets told that applicationDidEnterBackground, and can request a moment to finish "one last thing". See here under "Executing Finite Length Tasks".
There (iIn the dispatch block suggested by the sample code), save the object that counts views (saveInBackgroundWithBlock:), invalidate the timer, and tell iOS you're done with [application endBackgroundTask:bgTask];
What I should is store the video's somewhere else and save 1 view per click.
You can save this click in the background using something like this:
userClick.saveInBackground()
It saves the click in a background proces so the user doesn't have to wait for the sync with Parse.
note: You should use Bolts (https://github.com/BoltsFramework/Bolts-iOS) to get saveInBackground() working.
* edit *
Maybe it's smart to sync with parse every x amount of clicks, maybe 5 or 10. To limit the amount of requests.
Related
How do I set a limit for loading messages in a chat to save user traffic? Let's say there are 10,000 messages. If we download everything, it will take an unimaginable amount of traffic. What if there are pictures? And so will be loaded only let's say 30. And it will load 30 messages at a time when scrolling. Please help me. Thank you in advance. I use a translator.
the answer splits into 2:
the request from the server should allow the limitation of the number of objects. for the sake of the example if the API is using GET, then the request might look like URL/messages.api?from=1&to=30
for scrolling purposes you keep a counter variable, then have an onScroll event set that would call a function to call the API for the next set of messages, and render the results.
if you'd add code I can be more specific
you can look at an example code that I wrote here:
https://42knots.midrehov.com/42/apps/news.html
In my Project Management app I want to solve the issue of multiple users viewing the same Task record and 1 or more of them updating some of the Tasks Data while the others are viewing it.
Here is a scenario...
User #1 views Task #1 and User #2 views Task #1
Now User #2 updates the Task #1 Description
User #1 is now viewing the Task record but his view shows a different out-dated Description since User #2 had just updated it! Even worse he may want to edit the description himself which would completely over-write User #2's Description update.
That is 1 example of the issue. Just add more users and the issue multiplies!
Ideally I would use something like Sockets or a service like Pusher.com to update the data for all users as soon as an update by any user is made. However this project is going to be on hundreds of servers and has limited capabilities as far as server requirements so sockets and even a service like Pusher are out of the question!
Another idea for a solution is based on what Twitter does. If you view a persons Twitter page and they make a new post while you have there page loaded. It will show a notification message DIV to tell you there are X number of new posts and give you a link to click to reload the stream of posts with the latest posts.
I believe a similar approach could work for my project. If a user makes an update to any Task data while other users are viewing that Task record. It would show a Notification message on the Task modal window telling the user that the Task data has been updated and that they should reload the Task.
To make this work I know there will need to be some AJAX request made at some interval.
That AJAX request would then need to compare the timestamp of the last update made on the Task record and compare it with the time the user viewing the Task record started viewing it or since they last reloaded the task.
I feel like my logic is missing a piece of the puzzle though? Is this all correct or am I missing something?
Can someone explain how I can do this or tell me if what I have in mind is right?
I know that in short I simply need to determine if the Task last modified Timestamp is AFTER the other user started viewing the Task. At some point though I feel the users time should be updated too?
UPDATE
I completely forgot that Stack Overflow does this exact task on questions and answers! When you view a page on SO and a Answer is updated it will show a notification message telling you to reload the answer and provide a link to reload it. That is what I want to do!
StackOverflow uses Web Sockets to do this but in my app which is a plugin to be used on many different server configurations, I cannot use Sockets. I am trying to achieve similar result with AJAX. Even if it's an AJAX request made every 30 seconds to get the task modified Time and compare it to another to determine if user should reload task data would work in my case
Your question is too broad, but you are basically describing a Pub/Sub.
Idea
Whenever a user enters your site, he gets a token to identify them.
If he accesses a task, he subscribes to that task, which means that any modification on it would be alerted to him.
He polls the server to check if there is any alert to him.
Implementation
Regarding implementation, you can set-up a list with each user's subscriptions.
Using your example:
User1 subscribes to (Task1, Task2)
User2 subscribes to (Task1)
With each subscription, you keep some value that represents the last state the user has about that topic (e.g, the last modification timestamp).
The user polls your application every n seconds. Whenever the request reaches your application, you check the user's subscriptions, and check if the timestamp has changed (if they have the latest). If so, you update the last state that the user has and retrieves him the new values for the tasks that changed.
Things to consider
This list of subscriptions will be constantly accessed, so becareful where you are going to store it. If in memory, consider that you will need to share it across the different instances (if you are load balancing). You can use Redis, or something like that.
You do not need to go to your database everytime you need to retrieve data. If someone is subscribing to it, keep it on a cache.
The concept and idea is fairly trivial, and the implementation shouldn't be any more difficult. You need a Last Updated timestamp for each task as you say, as well as a Last Update timestamp on the client if you go with the described approach. Generally, when a User is viewing a Task, you'd want to (on the client side, Javascript):
Query the server for the Last Updated timestamp of the Task being viewed with AJAX.
If the Last Updated timestamp of the Task being viewed is greater (newer) than the Last Update timestamp on the client goto step 5.
Wait (asynchronously) n seconds.
Goto step 1.
Notify User that the Task being viewed has been updated.
End (since it is already known to the client that the Task has been updated, there is no need to keep polling whether it's been updated or not).
One approach could be simply creating an asynchronous interval using setInterval() that would be cleared once it has been determined an update occurred, and the user is shown a message afterwards.
var lastUpdate = Date.now();
var intervalDuration = 30000; // 30 seconds
var interval = setInterval(function () {
var xhr = new XMLHttpRequest();
...
xhr.onload = function () {
if (...) { // if the Task's Last Updated timestamp is newer than lastUpdate
clearInterval(interval);
// show message to user that the Task has been updated
}
};
}, intervalDuration);
I can imagine in a significantly massive system this approach could be easily inadequate, but for non-enterprise grade solutions or for follow-up UI improvements this can be a quick, cheap, and spectacular solution.
Of course there are potentially more robust and flexible alternatives to this: long-polling or websockets.
So I have certain profile pages that needs to have page views. I stored the view data in mysql and php (actually laravel). Basic idea is to add view by 1 every time the profile is visited.
Basic idea is to add a php code in the profile page, like
$page->view += 1; $page->save();
But what if the user hits f5 several times? It will cause the query to run a lot and I fear it will eventually slow the app.
I was thinking of making a prompt with js when user hits f5 and an ajax call to add the view. But I was wondering if there is a better solution (like, how did youtube do their views)?
You can count the views after a certain amount of time on the page.
To achieve this, you will need a delayed javascript function like:
setTimeout(function(){countView()},3000); (3 second delay)
Where countView() should be an ajax call to a function that runs $page->view += 1; $page->save();
And since Ajax calls are asynchronous, the execution will not delay your application flow, although a simple increment on a page-view table should not do much harm in terms of performance
This will work as long as the user doesnt delete the cookies.
if ($_COOKIE['returning']!="yes")
{
// first visit!
}
setcookie("returning", "yes", time()+360000);
Another way would be to log the IP in a database and check if user already visited, but the code is more complex than i can post right now. I will edit the post later if accepted.
Right now I'm using AJAX to pull in a list of active streams (TwitchTV) and it's viewers and I'm requesting this every second. At time the list of streams to check can get quite lengthy so I plan on splitting the ajax requests into 2 or 3 parts:
1) Get Number of Viewers for Current Stream (Check every 1 Second)
2) Split Stream in Half and Check 1st Half of List for Active Streamers (Check every 5 Seconds)
3) Check 2nd Half of List for Active Streamers (Check every 5 Seconds)
so I would have 3 requests running simultaneously but I'm worried about what the load time will come down to. Since it is constantly pulling in data would it make the page slower? Would the user likely notice? Is it better to keep 1 ajax request for big amounts of data or is it better to use multiple ajax requests for smaller pieces of data? Is ajax really the best thing to pull in constantly changing live data?
The answer to your various questions is probably "It depends":
The ajax requests by themselves shouldn't make anything slower. These are asynchronous requests, so they will only actually cause the user's browser any significant (and probably still not noticeable) load when the request completes.
One thing that could potentially slow your app down (or cause the user to notice in an unpleasant way) is the DOM manipulation when the request completes. Changing your current number of streaming users in-place probably won't hurt, but depending on the number of streams/how you are displaying them in a list, redrawing this could potentially be very expensive/cause lag on things like redraw.
An alternative to using Ajax (depending on what browsers you wish to support) is to use websockets. This way you can keep a connection open and the server can tell the application when the data needs to change, instead of the need to poll for it.
Why do you need to break your list up into a first half and a second half?
One way to cut down on the amount of data you're sending back and forth might be to send some sort of signal indicating the last bit of data you received. For example, when your timeline on twitter.com updates every few seconds, the ajax request sends along the id of the most recent tweet it received, so that the server knows not to waste time sending any data older than that. Depending on your use case this might be effective.
I'm working on something similar to a pastebin (yeah, it's that generic) but allowing for multiple user editing. The obvious problem is that of multiple users attempting to edit the same file. I'm thinking along the lines of locking down the file when one user is working on it (it's not the best solution, but I don't need anything too complex), but to prevent/warn the user I'd obviously need a system for monitoring each user's edit sessions. Working with database and ajax, I'm thinking of two solutions.
The first would be to have the edit page ping the server at a arbitrary interval, say a minute, and it would update the edit session entry in the db. Then the next time a script request to edit, it checks for the most recent ping, and if the most recent was another arbitrary time ago, say five minute, then we assume that the previous user had quited and the file can be edited again. Of course, the problem with this method is that the assumption that the previous user had quited is simply an assumption. He could be having flaky wi-fi connection and simply dropped out for ten minutes, all the time with the window still open.
Of course, to deal with this problem, we'd have to have the server respond to new request from previously closed sessions with an error, telling the client side to point out to the user that his session has ended, and then deal with it by, say, saving it as another file on the server and asking the user to manually merge it, etc. It goes without saying that this is rather horrible for the end user.
So I've came around to think of another solution. It may also be possible to get a unload event to fire when the user's session ends, but I cannot be sure whether this will work reliably.
Does anybody has any other, more elegant solution to this problem?
If you expect the number of concurrent edits to the file to be minor, you could just store a version number for the file in the db, and when the user downloads the file into their browser they also get the version number. They are only allowed to upload their changes if the version number matches. First one to upload wins. When a conflict is detected you should send back the latest file and the user's changes so that the user can manually merge in the changes. The advantage is that this works even if it's the same user making two simultaneous edits. If this feature ends up being frequently used you could add client-side merging similar to what a diff tool uses (but you might need to keep the old revisions in that case).
You're probably better off going for a "merge" solution. Using this approach you only need to check for changes when the user posts their document to the server.
The basic approach would be:
1. User A gets the document for editing, document is at version 1
2. User B gets the document for editing, document is at version 1
3. User B posts some changes, including the base version number of 1
4. Server updates document, document now at version 2
5. User B posts some changes, including the base version number of 1
6. Server responds saying document has changed since the user starts editing, and sends user the new document, and their version - user will then need to perform any merging of their changes into document version 2, and post back to the server. User is essentially now editing document version 2
7. User A posts some changes, including the version number of 2
8. Server updates the document, which is now at version 3
You can still do a "ping" every minute, to get the current version number - you already know what version they're editing, so if a new version is available you can let them know and let them download the latest version to make their changes into.
The main benefit of this approach is that users never lock files, so you don't need any arbitrary "time-outs".
I would say you are on the right track. I would probably implement a hybrid solution:
Have a single table called "active_edits" or something like that with a column for the document_id, the user, and the last_update_time. Lets say your ping time is 1 minute and your timeout is 5 minutes. So a use-case would look like this:
Bob opens a document. It checks the last_update_time. If it is over 5 minutes ago, update the table with Bob and the current time. If it is not, someone else is working on the document, so give an error message. Assuming it is not being edited, Bob works on the document for a while and the client pings an update time every minute.
I would say do include a "finish editing" button and a onunload handler. Onunload, from what I understand can be flaky, but might as well add it. Both of these would send a single send-only post to the server saying that Bob is done. Even if Bob doesn't hit "finish editing" and onunload flakes out, the worst case is that another user would have to wait 5 more minutes to edit. The advantage is that if these normally work (a fair assumption) then the system works a bit better.
In the case you described where a Bob is on a bad wireless connection or takes a break: I would say this isn't a big deal. Your ping function should make sure that the document hasn't been taken over by someone else since Bob's last ping. If it has, just give Bob a message saying "someone else has started working on the document" and give them the option to reload.
EDIT: Also, I would be looking into window.onbeforeunload, not onunload. I believe it executes earlier. I believe this is the function website (slashdot included) use to allow you to confirm that you actually want to leave the page. I think it works in the major browsers except Opera.
As with this SO question How do you manage concurrent access to forms?, I would not try to implement pessimistic locking. It is simply too difficult to get working reliably in a stateless environment. Instead, I would use optimistic locking. However, in this case I used something like a SHA hash of the file to determine if the file had changed since the user last read from the file. For each request to change the file, you would run a SHA hash of the file bytes and compare it with the version you pulled when you first read the data. If had changed, you reject the change and either force the user to do their edits again (pulling a fresh copy of the file contents) or you provide a fancier conflict resolution.