8

I am going to take a crack at building a penny auction site for a specific niche using angular JS. I am trying to plan the countdown timers and i've been itching for a reason to try out firebase.

I had the idea yesterday to have each auction somehow have a countdown in the actual database, because with 2 way data binding, peoples clientside will always stay updated.

When the firebase changes, all the connected clients instantly change. So my question is this... How could I do a server side countdown within a particular record.

So say I had a record for item x and it had all that items information and one of the array keys is "countdown: 59:01:00". What is a realistic and scalable way to countdown from 59:01:00 to 00:00:00 on the SERVER side.

I was thinking maybe a cronjob that runs every 1 second? But then with hundreds of database entries running hundreds of countdowns each second, the server would probably crash.

Any good ideas?

Daniel White
  • 3,337
  • 8
  • 43
  • 66
  • 2
    Have the server calculate the expiration date and time and give that to the client, letting the client handle the countdown. – PitaJ Jul 31 '14 at 05:21
  • I don't feel that that will be accurate enough for a penny auction situation when people wait till the last SECOND to click. I think the solution i mention above is MUCH safer and more reliable for end users. Something where the server says there are 50 seconds left and all the clients update in realtime (the beauty of firebase, comet, socket.io, etc) – Daniel White Jul 31 '14 at 05:31
  • If the accuracy of a client side timer is problematic for you, think about including latency between the client and the server and how that could cause problems. You could always validate server side on every click. – PitaJ Jul 31 '14 at 05:49
  • Ok I here you. So if every time someone clicked it "reset" the timer to say 10 minutes... What would the server side validation look like? I'm not quite wrapping my head around this. So the database would just have the "end date" and the timer would always be based off "server time" and not client side time, for accuracy reasons, right? – Daniel White Jul 31 '14 at 05:51
  • Every time someone loaded the page, the server would tell the client how much time there was left on the item. Then, the client would display a toner which would decrement every second or whatever, and would maybe check every so often to synchronize itself with the server. When the button was clicked, a query would be sent to the server, the server would then check it's own current time against the closing time in the database, and if it was valid, would but the item or whatever. – PitaJ Jul 31 '14 at 05:56
  • You're helping me understand this and I appreciate it. A few more questions. So... the point of "checking every so often to synchronize" would just be like getting the end date in seconds and making sure the client side timer is accurate down to the second right? Now when a client clicks the bid button and the timer resets to say, 10 minutes left, then really all the other clients would update if two-way data binding was in existence, right? So I think you have helped me figure this out if my first statement is correct lol. – Daniel White Jul 31 '14 at 06:00
  • You should really use websockets to get updated about other user's clicks and change the timer then. – PitaJ Jul 31 '14 at 06:09
  • Well thats essentially what firebase is. If a user clicks "bid" it would just change the "end date" in firebase and all the connected clients would instantly update. – Daniel White Jul 31 '14 at 06:12
  • That sounds fine. I just wouldn't suggest using it for the timer itself, because there would be a lot of traffic updating it every second when it could just be done by the client. – PitaJ Jul 31 '14 at 06:13
  • I'm going to post an answer tomorrow. Please accept it as it will allow later users to more easily see your solution (and it will give me reputation) – PitaJ Jul 31 '14 at 06:17

2 Answers2

11

Firebase could indeed handle hundreds of database operations every second (many more in fact). But this would be greatly over-engineered.

Instead of running a timer that updates every second on the server, simply store the start/stop times of the event and allow the clients to manage their own timers. This should not be done by decrementing by 1 every second (as setInterval and other client-side tools are not very exact) but by comparing the current timestamp to the end, and determining the difference.

timeout = setInterval(countDown, 1000);
function countDown() {
    setTime(Math.max(0, endsAt - Date.now()));
    if( endsAt <= Date.now() ) { clearInterval(timeout); }
}

function setTime(remaining) {
    var minutes = Math.floor(remaining / 60000);
    var seconds = Math.round(remaining / 1000);
    $('#timer').text(lpad(minutes) + ':' + lpad(seconds));
}

Most likely, the reason you want the server in charge of the timer is to make it "fair." But this isn't logical. If each user keeps their own "ticker" down to the end time, and the start/end time are fixed, there is nothing to hack here.

Kato
  • 40,352
  • 6
  • 119
  • 149
  • Hi! Is there a "newer" and/or simpler way to implement a Firebase countdown timer in Android Studio (java)? Your answer is 2+ years old and Firebase changed a lot since. Thanks! – Dake Jan 13 '17 at 20:29
  • My partner posted the following question if you'd like to answer there: http://stackoverflow.com/questions/41648186/implementing-a-firebase-server-side-countdown-timer-for-android – Dake Jan 14 '17 at 17:19
1

I was dealing with similar problem as you do.

The problem number one is that there is no server side code. Firebase is data storage and whatever logic you have to implement needs to be divided into database design and client side code.

The second problem how to make client listen to time stamp change from future to past if the actual time stamp field in database is not changed.

Client can always ask for current server time by pushing time stamp placeholder and listening to change.

auction:{
  countdown:{
    ends_in: NUMBER_IN_MLS,
    start_time: TIME_STAMP
  }
}

users_current_time: TIMESTAMP_PLACEHOLDER

if user starts on the app and wants to see current auctions the current server time is immediatelly pulled and the timer on client side starts from 0. - This action can be repeated everytime user goes Online. Now when the user pulls the auction he will get the time when it started and the duration. You also have the current server time and the time you are online. This should give you quite precise information on how much time is left.

Third problem: My bigger concern here would be security. The auction should be closed once the time is up however with only firebase as backend all clients still have write permission to submit their bids.

I still would recommend some server which would do all the housekeeping and calculating the countdown.

webduvet
  • 4,220
  • 2
  • 28
  • 39