Skip to content

Small two-side javascript library to keep clients and server in sync

License

Notifications You must be signed in to change notification settings

craig-harbottle/synchazard

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

53 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Known Vulnerabilities

SyncHazard

This small project aims to minimize client side data requests


How it works

The core are the WebSockets for the communication layer and WebWorkers to put aside the client-side collaboration.
The server runs some kind of IFTTT like procedure that could be triggered by anything (fs watching, db hooks, kafka consumers, ...) and using a websocket broadcasts to all connected clients the relevant metadata needed to get the actual data. Now the client decides what to do and, in case it wants to proceed, it knows exactly how to: just forward the metadata to the WebWorker which starts his job (could be a xhr request or could use the websocket as well) using the information contained in the metadata. Once the request is done the response is given to a handler that knows exactly how to consume it.


Expectations

  • Get rid of most of API requests triggered by user events.
  • Being able to really exploit the state of stateful frontend frameworks.
  • Enable automated synchronization among all clients stairing at the same data.

Install dependencies, build libs and samples

Simply run:

> npm i && npm run build

and let it go, the build itself will be fast, and will observe/rebuild anything relevant on the source folder... then open another terminal window.

Now everything is set, just start it.

> npm start

and open one or more browsers on http://localhost:4000


Test broadcast to more clients within LAN

Get the current LAN ip of the machine running the server:

> ifconfig en0 | grep inet | grep -v inet6 | awk '{print $2}'

assume it is 192.168.5.107

now open the vars.json file in the root of the project and edit the DOMAIN_OR_IP value so that it contains the found IP address.

The servers have to be restarted, go in the terminal where npm start has been launched, press ctrl + c and relaunch `em.

Now on one or more clients open a browser and navigate to http://192.168.5.107:4000 standing this is the port and IP address set as CLIENT.PORT and DOMAIN_OR_IP in the vars.json file.


What is in the samples

I will assume here that the build is done using the local IP address 192.168.5.107 and that the ports have not been changed.

here there are 4 handlers connected to in one or two-way mode to server Actions:

  • datajson
    the Action on the dataServer, when the client connects, sends back a metadata that contains all information to get the initliaization data; on the client a WebWorker knows he must trigger an xhr request to get the resource (/dataServer/data1.json) and once the response is available, it forwards the payload to the handler function; the handler on the client side just uses it to render a title in the middle of the page, an image with a link and a small sentende below the image. The server Action does something more: watches the file and whenever a change occur to it it uses the websocket to broadcast the json to all connected clients, where the data will be consumed by the handler.

    • client handler: /server/js/handlers/jsonObserver.js
    • server Action: /dataServer/actions/jsonObserver.js
  • script
    the dataServer Action for this is pretty similar to the datajson sample, there's a simple watcher on a file (/dataServer/js/lib/sync_script.js); what is different is the client handler function, it just inject the script. So it is possible for example inject a script that can do quite a lot, on all clients. If You uncomment the right lines and simply save the file then the injected script will inject a rude ingorant assertion tester that will run on all clients a couple of tests, checking that exactly two anchors are in the dom and that a canvas tag is rendered. The title will show the outcome, in case of errors also the browser console will show the assertion messages.

    • client handler: /server/js/handlers/script.js
    • server Action: /dataServer/actions/script.js
  • style
    again quite boring watcher on /dataServer/css/sync_style.css, on change will be injected and will change the style on all clients.

    • client handler: /server/js/handlers/style.js
    • server Action: /dataServer/actions/style.js
  • hundredRandom
    the Action on the dataServer simply broadcasts regularly a random number ∈ [0,100]; the clients handlers simply renders a live line chart adding one point each time it receive the value through the socket.

    • client handler: /server/js/handlers/randomPercentage.js
    • server Action: /dataServer/actions/randomPercentage.js
  • reactor
    Nothing to do with React, but the name fits in somehow. Here I think there is a more clear hazard. And maybe it would be boring to read a long pseudo-description of the flow. But it's worth to try out to summarize the functionality. I wrote a small client library to enable on targeted input[text] and textarea tags some sort of concurrrency. Basically whenever the client Alice start typing in one of the target tags, immediately all other clients see the tag being edited as disabled, when Alice leave the focus on the tag, all other clients will see that tag enabled and filled with the value Alice entered.

    • client handler: /server/js/handlers/reactor.js
    • server Action: /dataServer/actions/reactor.js
  • incremental
    this is the simplest one, the Action broadcasts evey second an incremental counter; the client handler simply render it somewhere.

    • client handler: /server/js/handlers/incremental.js
    • server Action: /dataServer/actions/incremental.js

Almost in all cases a WebWorker runs a proxy between the client side socket and the handler function, allowing for example to the datajson example to receive simple metadata sent by the dataServer containing all the information needed to get the real resource, the webWorker then decides in this case to start an xhr request for the resource and when the data is available it forwards all to the handler function that decides how to consume it. In any case the WebWorker decide in the end which one is the handler function that will consume the data. The WebWorker used in the main example is /server/js/workers/worker.js

A raw distributed computing sample to get (a bad) value for π using other clients that will accept to help. ... to be continued

A couple of collaborative textareas where the content and the size is shared among all clients ... to be continued

A basic chat, here is used also the ability to send a message only to the client that sent one message (check the console when a message is posted) ... to be continued

The most simple immaginable example using React ... to be continued

This may look wierd cause in the end the ws srv sends to the client one specific function that will be used to make a naive calculation.
... to be continued


Clean, use it

The default build script creates a lot of sample files useful only as samples, if you want to build the few files really needed to exploit Synchazard just run

> npm run base

then use them on client and on the server, adding actions and handlers files as needed.


guess what
again ... to be continued, meanwhile feel free to reach me out for any question federico.ghedina@gmail.com

About

Small two-side javascript library to keep clients and server in sync

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 51.9%
  • CSS 35.1%
  • HTML 13.0%