An Auction System Needs a Central Clock
Tags: auction, laravel, node, socketio
Published: 2020-10-08 09:14:06



# An Auction Runs by A Clock

An auction system either live or timed runs by the clock. In a live auction, one often runs calls on a bid according to a clock. In a timed auction, you start and end an auction by the clock, and you show the users a countdown timer. 

# Browser Times Cannot Be Trusted

In a browser, `new Date()` gives you the user local time, according to the user's computer local time. As users reside in different time zones, and moreover may have inaccurate computer clock, or they may just intentionally modify that clock, the local time will be different. 

Obviously, one cannot let the user observe any time-dependent functionality, and make any time-dependent action, based on a clock which is the same for all users of the auction system.   

# A Central Clock is Needed

Hence, an auction system logically needs a central clock, and that clock has to be projected to all users in all case where relative times, such as a countdown timer, or absolute times, such as auction start and end times, are observed by the user on a web page. The web page might show absolute times in the user time zone, but the local time has to be derived from the central clock. 

Such a central clock has to be implemented at the server, as this is the only place where we can rely on. And needs to be transmitted to the user web page. 

Such a transmission can be either upon a time-based event, such as auction start or end or periodically, with the web page adjusting the content dynamically, such as advancing a countdown timer. 

The presence of a central clock implies the need for a real-time web application to which the server sends updates. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/1lyqt6kedsk3zp5vl26q.jpg)

# Implementing a Central Clock 

## Node.js

### Server-Side

Integrate the web page and the server with [Socket.IO](https://socket.io). 

At the server run `setTimeout` or `setInterval`, for an event-based action or periodic update, respectively. 

### Front-End Event-Based

At the front-end listen to a socket event for an event-based auction, e.g.

		socket.on('advanceCall', (data) => {});
	
Or

    socket.on('startAuction', (data) => {});
    
    
### Front-End Periodic

    socket.on('time', (data) => {});

## Laravel
 
### Server-Side

Use [ReactPHP](https://reactphp.org) to implement a timer, either periodic, 

	$timer = $loop->addPeriodicTimer($time, function() 
		use(&$task) {
    broadcast(new TimeSignal(json_encode(...)));
	});

where `TimeSignal` is a [Laravel event](https://laravel.com/docs/7.x/events#introduction). 

Or one time,
 
 	$timer = $loop->addTimer($time, function() 
		use(&$task) {
			 broadcast(new AuctionCall(json_encode(...))); 
	});

where `AuctionCall` is a Laravel event.

For more details, see my article [Timer Server in ReactPHP](https://yoramkornatzky.com/post/timer-server-in-reactphp).

Events are broadcast using [Laravel Echo Server](https://github.com/tlaverdure/laravel-echo-server) or [Laravel Websockts](https://beyondco.de/docs/laravel-websockets/getting-started/introduction)

### Front-End

Listen for events with Socket.io, 

    window.Echo.channel('auction-events')
      .listen('startAuction', (e) => {
            
      });

Or

		  
	   window.Echo.channel('time-signal')
       .listen('time', (e) => {
            
        });