SlideShare uma empresa Scribd logo
1 de 75
Baixar para ler offline
Implementing Server Side 
Data Synchronization for 
Mobile Apps
Michele Orselli 
CTO@Ideato 
! 
_orso_ 
! 
micheleorselli 
! 
mo@ideato.it
Agenda 
scenario design choices 
implementation alternative approaches
Sync scenario 
A 
B 
C
Sync scenario 
A 
B 
C 
A 
B 
C 
A 
B 
C
Dealing with conflicts 
A1 
A2 
?
Scenario 
Brownfield project 
! 
several mobile apps for tracking user generated data 
(calendar, notes, bio data) 
! 
iOS & Android 
! 
~10 K users steadily growing at 1.2 K/month
Scenario 
MongoDB 
! 
Legacy App based on codeigniter 
! 
Existing RPC-wannabe-REST API for data sync
Scenario 
get updates: 
! 
POST /m/<app>/get/<user_id>/<res>/<updated_from> 
! 
! 
! 
send updates: 
! 
POST /m/<app>/update/<user_id>/<res_id>/<dev_id>/<res> 
! 
!
api
Scenario 
! 
! 
6 different resources, 12 calls per sync 
! 
apps sync by polling every 30 sec 
! 
every call sync little data 
! 
!
Challenge 
! 
! 
rebuild sync API for old apps + 2 incoming 
! 
allow image synchronization 
! 
more efficient than previous API 
! 
!
Existing Solutions 
Tstamps, 
Vector clocks, 
CRDTs 
syncML, 
syncano 
Algorithms Protocols/API 
Azure Data 
sync 
Platform 
couchDB, 
riak 
Storage
Not Invented Here? 
Don't Reinvent The Wheel, 
Unless You Plan on Learning More About Wheels 
! 
J. Atwood
Architecture 
! 
! 
2 different mobile platforms 
several teams with different skill level 
! 
changing storage wasn’t an option 
forcing a particular technology client side wasn’t an option
Architecture 
c1 
server 
c2 
c3 
sync logic 
conflicts resolution 
thin clients
Implementation 
! 
! 
In the sync domain all resources are the same 
! 
For every app 
one endpoint for getting new data 
one endpoint for pushing changes 
one endpoint for uploading images
Get changes 
! 
Get all changes (1st sync): 
! 
GET /apps/{app}/users/{user_id}/changes 
! 
Get latest changes: 
! 
GET /apps/{app}/users/{user_id}/changes?from={from}
Get changes 
! 
Get all changes (1st sync): 
! 
GET /apps/{app}/users/{user_id}/changes 
! 
Get latest changes: 
! 
GET /apps/{app}/users/{user_id}/changes?from={from} 
timestamp?
Server suggest the sync time 
timestamp are inaccurate (skew and developer errors) 
! 
server suggests the “from” parameter to be used in the 
next request 
GET /changes 
c1 server 
{ ‘next’ : 123456, 
‘data’: […] }
Server suggest the sync time 
GET /changes 
{ ‘next’ : 12345, 
‘data’: […] } 
c1 server
Server suggest the sync time 
GET /changes 
{ ‘next’ : 12345, 
‘data’: […] } 
c1 server 
GET /changes?from=12345 
{ ‘next’ : 45678, 
‘data’: […] }
what to transfer 
operations: 
{‘op’: ’add’, id: ‘1’, ’data’:[…]} 
{‘op’: ’update’, id: ‘1’, ’data’:[…]} 
{‘op’: ’delete’, id: ‘1’} 
{‘op’: ’add’, id: ‘2’, ’data’:[…]} 
! 
! 
states: 
{id: ‘1’, ’data’:[…]} 
{id: 2’, ’data’:[…]} 
{id: ‘3’, ’data’:[…]}
what to transfer 
! 
we chosen to transfer states 
{id: ‘1’, ’type’: ‘measure’, ‘_deleted’: true} 
{id: 2’, ‘type’: ‘note’} 
{id: ‘3’, ‘type’: ‘note’} 
! 
! 
ps: soft delete all the things!
unique identifiers 
How do we generate an unique id in a distributed system? 
! 
UUID: several implementations (RFC 4122) 
! 
Local Ids/Global Id: server generates GUIDs 
clients use local ids to manage their records 
GET /changes 
c1 server 
{‘data’:{’guid’: ‘58f0bdd7-1481’}}
unique identifiers 
POST /merge 
{ ‘data’: [ 
{’lid’: ‘1’, …}, 
{‘lid’: ‘2’, …} 
] } 
c1 server 
{ ‘data’: [ 
{‘guid’: ‘58f0bdd7-1400’, ’lid’: ‘1’, …}, 
{‘guid’: ‘6f9f3ec9-1400’, ‘lid’: ‘2’, …} 
] }
conflict resolution algorithm (plain data) 
! 
server handles conflicts resolution 
mobile generated data are “temporary” until sync to server 
! 
conflict resolution: 
domain indipendent: last-write wins 
domain dipendent: use domain knowledge to resolve
conflict resolution algorithm (plain data) 
function sync($data) {! 
! 
! foreach ($data as $newRecord) {! 
! 
! ! $s = findByGuid($newRecord->getGuid());! 
! ! 
! ! if (!$s) {! 
! ! ! add($newRecord);! 
! ! ! send($newRecord);! 
! ! ! continue;! 
! ! }! ! 
! ! ! 
! ! if ($newRecord->updated > $s->updated) {! 
! ! ! update($s, $newRecord);! 
! ! ! send($newRecord);! 
! ! ! continue;! 
! ! }! 
! ! ! 
! ! updateRemote($newRecord, $s);! 
}
conflict resolution algorithm (plain data) 
function sync($data) {! 
! 
! foreach ($data as $newRecord) {! 
! 
! ! $s = findByGuid($newRecord->getGuid());! 
! ! 
! ! if (!$s) {! 
! ! ! add($newRecord);! 
! ! ! send($newRecord);! 
! ! ! continue;! 
! ! }! ! 
! ! ! 
! ! if ($newRecord->updated > $s->updated) {! 
! ! ! update($s, $newRecord);! 
! ! ! send($newRecord);! 
! ! ! continue;! 
! ! }! 
! ! ! 
! ! updateRemote($newRecord, $s);! 
}
conflict resolution algorithm (plain data) 
function sync($data) {! 
! 
! foreach ($data as $newRecord) {! 
! 
! ! $s = findByGuid($newRecord->getGuid());! 
! ! 
! ! if (!$s) {! 
! ! ! add($newRecord);! 
! ! ! send($newRecord);! 
! ! ! continue;! 
! ! }! ! 
! ! ! 
! ! if ($newRecord->updated > $s->updated) {! 
! ! ! update($s, $newRecord);! 
! ! ! send($newRecord);! 
! ! ! continue;! 
! ! }! 
! ! ! 
! ! updateRemote($newRecord, $s);! 
} 
no conflict
conflict resolution algorithm (plain data) 
function sync($data) {! 
! 
! foreach ($data as $newRecord) {! 
! 
! ! $s = findByGuid($newRecord->getGuid());! 
! ! 
! ! if (!$s) {! 
! ! ! add($newRecord);! 
! ! ! send($newRecord);! 
! ! ! continue;! 
! ! }! ! 
! ! ! 
! ! if ($newRecord->updated > $s->updated) {! 
! ! ! update($s, $newRecord);! 
! ! ! send($newRecord);! 
! ! ! continue;! 
! ! }! 
! ! ! 
! ! updateRemote($newRecord, $s);! 
} 
remote wins
conflict resolution algorithm (plain data) 
function sync($data) {! 
! 
! foreach ($data as $newRecord) {! 
! 
! ! $s = findByGuid($newRecord->getGuid());! 
! ! 
! ! if (!$s) {! 
! ! ! add($newRecord);! 
! ! ! send($newRecord);! 
! ! ! continue;! 
! ! }! ! 
! ! ! 
! ! if ($newRecord->updated > $s->updated) {! 
! ! ! update($s, $newRecord);! 
! ! ! send($newRecord);! 
! ! ! continue;! 
! ! }! 
! ! ! 
! ! updateRemote($newRecord, $s);! 
} 
server wins
conflict resolution algorithm (plain data) 
{ ‘lid’: ‘1’, 
‘guid’: ‘af54d’, 
‘data’ : ‘AAA’ 
‘updated’: ’100’ } 
{ ‘lid’: ‘2’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } 
c1 
{ ’guid’: ‘af54d’, 
‘data’: ‘BBB’, 
‘updated’ : ’20’ } 
server
conflict resolution algorithm (plain data) 
{ ‘lid’: ‘1’, 
‘guid’: ‘af54d’, 
‘data’ : ‘AAA’ 
‘updated’: ’100’ } 
{ ‘lid’: ‘2’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } POST /merge 
{ ’guid’: ‘af54d’, 
‘data’: ‘BBB’, 
‘updated’ : ’20’ } 
c1 server
conflict resolution algorithm (plain data) 
{ ‘lid’: ‘1’, 
‘guid’: ‘af54d’, 
‘data’ : ‘AAA’ 
‘updated’: ’100’ } 
{ ‘lid’: ‘2’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } POST /merge 
{ ‘guid’: ‘e324f’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } 
{ ’guid’: ‘af54d’, 
‘data’: ‘BBB’, 
‘updated’ : ’20’ } 
c1 server
conflict resolution algorithm (plain data) 
{ ‘lid’: ‘1’, 
‘guid’: ‘af54d’, 
‘data’ : ‘AAA’ 
‘updated’: ’100’ } 
{ ‘lid’: ‘2’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } POST /merge 
{ ‘guid’: ‘e324f’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } 
{ ’guid’: ‘af54d’, 
‘data’: ‘BBB’, 
‘updated’ : ’20’ } 
c1 server
conflict resolution algorithm (plain data) 
{ ‘lid’: ‘1’, 
‘guid’: ‘af54d’, 
‘data’ : ‘AAA’ 
‘updated’: ’100’ } 
{ ‘lid’: ‘2’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } POST /merge 
{ ‘guid’: ‘e324f’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } 
{ ’guid’: ‘af54d’, 
‘data’: ‘AAA’, 
‘updated’ : ’100’ } 
c1 server
conflict resolution algorithm (plain data) 
{ ‘lid’: ‘1’, 
‘guid’: ‘af54d’, 
‘data’ : ‘AAA’ 
‘updated’: ’100’ } 
{ ‘guid’: ‘e324f’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } 
{ ’guid’: ‘af54d’, 
‘data’: ‘AAA’, 
‘updated’ : ’100’ } 
{ ‘lid’: ‘2’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } POST /merge 
c1 server 
{‘ok’ : { ’guid’: ‘af54d’ }} 
{‘update’ : { lid: ‘2’, ’guid’: ‘e324f’ }}
conflict resolution algorithm (hierarchical data) 
! 
How to manage hierarchical data? 
! 
! 
{ 
‘lid’ : ‘123456’, 
‘type’ : ‘baby’, 
… 
} 
{ 
‘lid’ : ‘123456’, 
‘type’ : ‘temperature’, 
‘baby_id : ‘123456’ 
}
conflict resolution algorithm (hierarchical data) 
! 
How to manage hierarchical data? 
1) sync root record 
2) update ids 
3) sync child records 
! 
! { 
‘lid’ : ‘123456’, 
‘type’ : ‘baby’, 
… 
} 
{ 
‘lid’ : ‘123456’, 
‘type’ : ‘temperature’, 
‘baby_id : ‘123456’ 
}
conflict resolution algorithm (hierarchical data) 
function syncHierarchical($data) {! 
! 
! sortByHierarchy($data);! 
! 
! foreach ($data as $newRootRecord) {! 
! ! ! 
! ! $s = findByGuid($newRootRecord->getGuid());! 
! ! ! 
! ! if($newRecord->isRoot()) {! 
! 
! ! ! if (!$s) {! 
! ! ! ! add($newRootRecord);! 
! ! ! ! updateRecordIds($newRootRecord, $data);! 
! ! ! ! send($newRootRecord);! 
! ! ! ! continue;! 
! ! ! }! ! 
! ! ! 
! ! ! …
conflict resolution algorithm (hierarchical data) 
function syncHierarchical($data) {! 
! 
! sortByHierarchy($data);! 
parent records first 
! 
! foreach ($data as $newRootRecord) {! 
! ! ! 
! ! $s = findByGuid($newRootRecord->getGuid());! 
! ! ! 
! ! if($newRecord->isRoot()) {! 
! 
! ! ! if (!$s) {! 
! ! ! ! add($newRootRecord);! 
! ! ! ! updateRecordIds($newRootRecord, $data);! 
! ! ! ! send($newRootRecord);! 
! ! ! ! continue;! 
! ! ! }! ! 
! ! ! 
! ! ! …
conflict resolution algorithm (hierarchical data) 
function syncHierarchical($data) {! 
! 
! sortByHierarchy($data);! 
! 
! foreach ($data as $newRootRecord) {! 
! ! ! 
! ! $s = findByGuid($newRootRecord->getGuid());! 
! ! ! 
! ! if($newRecord->isRoot()) {! 
! 
! ! ! if (!$s) {! 
! ! ! ! add($newRootRecord);! 
! ! ! ! updateRecordIds($newRootRecord, $data);! 
! ! ! ! send($newRootRecord);! 
! ! ! ! continue;! 
! ! ! }! ! 
! ! ! 
! ! ! …
conflict resolution algorithm (hierarchical data) 
function syncHierarchical($data) {! 
! 
! sortByHierarchy($data);! 
! 
! foreach ($data as $newRootRecord) {! 
! ! ! 
! ! $s = findByGuid($newRootRecord->getGuid());! 
! ! ! 
! ! if($newRecord->isRoot()) {! 
! 
! ! ! if (!$s) {! 
! ! ! ! add($newRootRecord);! 
! ! ! ! updateRecordIds($newRootRecord, $data);! 
! ! ! ! send($newRootRecord);! 
! ! ! ! continue;! 
! ! ! }! ! 
! ! ! 
! ! ! … 
no conflict
conflict resolution algorithm (hierarchical data) 
! 
! ! …! ! ! 
! 
! ! if ($newRootRecord->updated > $s->updated) {! ! ! ! 
! ! ! update($s, $newRecord);! 
! ! ! updateRecordIds($newRootRecord, $data);! ! ! 
! ! ! send($newRootRecord);! 
! ! ! continue;! 
! ! } else {! 
! ! ! updateRecordIds($s, $data);! 
! ! ! updateRemote($newRecord, $s);! 
! ! }! ! 
! } else {! 
! ! sync($data);! 
! }! ! 
}! 
remote wins
conflict resolution algorithm (hierarchical data) 
! 
! ! …! ! ! 
! 
! ! if ($newRootRecord->updated > $s->updated) {! ! ! ! 
! ! ! update($s, $newRecord);! 
! ! ! updateRecordIds($newRootRecord, $data);! ! ! 
! ! ! send($newRootRecord);! 
! ! ! continue;! 
! ! } else {! 
! ! ! updateRecordIds($s, $data);! 
server wins 
! ! ! updateRemote($newRecord, $s);! 
! ! }! ! 
! } else {! 
! ! sync($data);! 
! }! ! 
}!
conflict resolution algorithm (hierarchical data) 
{ ‘lid’: ‘1’, 
‘data’ : ‘AAA’ 
‘updated’: ’100’ } 
{ ‘lid’: ‘2’, 
‘parent’: ‘1’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } 
POST /merge 
c1 server
conflict resolution algorithm (hierarchical data) 
{ ‘lid’: ‘1’, 
‘data’ : ‘AAA’ 
‘updated’: ’100’ } 
{ ‘lid’: ‘2’, 
‘parent’: ‘1’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } 
c1 
server 
POST /merge 
{ ‘lid’: ‘1’, 
‘guid’ : ‘32ead’, 
‘data’ : ‘AAA’ 
‘updated’: ’100’ }
conflict resolution algorithm (hierarchical data) 
{ ‘lid’: ‘1’, 
‘data’ : ‘AAA’ 
‘updated’: ’100’ } 
{ ‘lid’: ‘2’, 
‘parent’: ‘32ead’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } 
c1 
server 
POST /merge 
{ ‘lid’: ‘1’, 
‘guid’ : ‘32ead’, 
‘data’ : ‘AAA’ 
‘updated’: ’100’ }
conflict resolution algorithm (hierarchical data) 
{ ‘lid’: ‘1’, 
‘data’ : ‘AAA’ 
‘updated’: ’100’ } 
{ ‘lid’: ‘2’, 
‘parent’: ‘32ead’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } 
c1 
server 
POST /merge 
{ ‘lid’: ‘1’, 
‘guid’ : ‘32ead’, 
‘data’ : ‘AAA’ 
‘updated’: ’100’ } 
{ ‘lid’: ‘2’, 
‘parent’: ‘32ead’, 
‘data’ : ‘hello!’, 
‘updated’: ’15’ } 
{‘update’ : { ‘lid’: ‘1’, ’guid’: ‘af54d’ }} 
{‘update’ : { lid: ‘2’, ’guid’: ‘e324f’ }}
enforcing domain constraints 
! 
! 
e.g. “only one temperature can be registered in a given day” 
! 
how to we enforce domain constraints on data?
enforcing domain constraints 
! 
! 
e.g. “only one temperature can be registered in a given day” 
! 
how to we enforce domain constraints on data? 
1) relax constraints
enforcing domain constraints 
! 
! 
e.g. “only one temperature can be registered in a given day” 
! 
how to we enforce domain constraints on data? 
1) relax constraints 
2) integrate constraints in sync algorithm
! 
! 
from findByGuid to findSimilar 
! 
first lookup by GUID then by domain rules 
! 
“two measures are similar if are referred to the same date” 
! 
! 
! 
! 
enforcing domain constraints
enforcing domain constraints 
c1 server
enforcing domain constraints 
{ ’guid’: ‘af54d’, 
‘when’: ‘20141005’ } 
c1 server
enforcing domain constraints 
{ ‘lid’: ‘1’, 
‘when’: ‘20141005’ } 
{ ’guid’: ‘af54d’, 
‘when’: ‘20141005’ } 
c1 server
enforcing domain constraints 
{ ‘lid’: ‘1’, 
‘when’: ‘20141005’ } 
{ ’guid’: ‘af54d’, 
‘when’: ‘20141005’ } 
POST /merge 
c1 server
enforcing domain constraints 
{ ‘lid’: ‘1’, 
‘when’: ‘20141005’ } 
{ ’guid’: ‘af54d’, 
‘when’: ‘20141005’ } 
POST /merge 
c1 server
enforcing domain constraints 
{ ‘lid’: ‘1’, 
‘when’: ‘20141005’ } 
{ ’guid’: ‘af54d’, 
‘when’: ‘20141005’ } 
POST /merge 
c1 server 
{ ’guid’: ‘af54d’, 
‘when’: ‘20141005’ }
dealing with binary data 
! 
Binary data uploaded via custom endpoint 
! 
Sync data remain small 
! 
Uploads can be resumed
dealing with binary data 
! 
Two steps* 
1) data are synched to server 
2) related images are uploaded 
! 
* this means record without file for a given time
dealing with binary data 
POST /merge 
{ ‘lid’ : 1, 
‘type’ : ‘baby’, 
‘image’ : ‘myimage.jpg’ } 
{ ‘lid’ : 1, 
‘guid’ : ‘ac435-f8345’ } 
c1 server 
POST /upload/ac435-f8345/image
What we learned 
! 
Implementing this stuff is tricky 
! 
Explore existing solution if you can 
! 
Understanding the domain is important
vector clocks
CRDT 
! 
Conflict-free Replicated Data Types (CRDTs) 
! 
Constraining the types of operations in order to: 
- ensure convergence of changes to shared data by 
uncoordinated, concurrent actors 
- eliminate network failure modes as a source of error
Math!!! 
CRDT 
! 
Bounded-join semilattices 
- join operation defining a least 
upper bound 
- partially order set 
- always increasing
Gateways handles sync 
Data flows through channels 
- partition data set 
- authorization 
- limit the data 
! 
Use revision trees 
Couchbase Mobile
Riak 
Distributed DB 
Eventually/Strong Consistency 
! 
Data Types 
! 
Configurable conflic resolution 
- db level for built-in data types 
- application level for custom data
! 
That’s all folks! 
Questions? 
! 
Please leave feedback! https://joind.in/11797 
!
Links 
Vector Clocks 
http://basho.com/why-vector-clocks-are-easy/ 
http://www.datastax.com/dev/blog/why-cassandra-doesnt-need-vector-clocks 
http://basho.com/why-vector-clocks-are-hard/ 
! 
CRDTs 
http://christophermeiklejohn.com/distributed/systems/2013/07/12/readings-in-distributed-systems. 
html 
http://www.infoq.com/presentations/problems-distributed-systems 
https://www.youtube.com/watch?v=qyVNG7fnubQ 
! 
Riak 
http://docs.basho.com/riak/latest/dev/using/conflict-resolution/ 
! 
Couchbase Sync Gateway 
http://docs.couchbase.com/sync-gateway/ 
http://www.infoq.com/presentations/sync-mobile-data 
! 
API 
http://developers.amiando.com/index.php/REST_API_DataSync 
https://login.syncano.com/docs/rest/index.html
Credits 
phones https://www.flickr.com/photos/15216811@N06/14504964841 
wat http://uturncrossfit.com/wp-content/uploads/2014/04/wait-what.jpg 
darth http://www.listal.com/viewimage/3825918h 
blueprint: http://upload.wikimedia.org/wikipedia/commons/5/5e/Joy_Oil_gas_station_blueprints.jpg! 
building: http://s0.geograph.org.uk/geophotos/02/42/74/2427436_96c4cd84.jpg! 
brownfield: http://s0.geograph.org.uk/geophotos/02/04/54/2045448_03a2fb36.jpg! 
no connection: https://www.flickr.com/photos/77018488@N03/9004800239! 
no internet con https://www.flickr.com/photos/roland/9681237793! 
vector clocks: http://en.wikipedia.org/wiki/Vector_clock! 
crdts: http://www.infoq.com/presentations/problems-distributed-systems

Mais conteúdo relacionado

Mais procurados

201410 2 fiware-orion-contextbroker
201410 2 fiware-orion-contextbroker201410 2 fiware-orion-contextbroker
201410 2 fiware-orion-contextbroker
FIWARE
 

Mais procurados (20)

JS Fest 2019. Anjana Vakil. Serverless Bebop
JS Fest 2019. Anjana Vakil. Serverless BebopJS Fest 2019. Anjana Vakil. Serverless Bebop
JS Fest 2019. Anjana Vakil. Serverless Bebop
 
React lecture
React lectureReact lecture
React lecture
 
Parse Advanced
Parse AdvancedParse Advanced
Parse Advanced
 
My Top 5 APEX JavaScript API's
My Top 5 APEX JavaScript API'sMy Top 5 APEX JavaScript API's
My Top 5 APEX JavaScript API's
 
Use Kotlin scripts and Clova SDK to build your Clova extension
Use Kotlin scripts and Clova SDK to build your Clova extensionUse Kotlin scripts and Clova SDK to build your Clova extension
Use Kotlin scripts and Clova SDK to build your Clova extension
 
Creating sub zero dashboard plugin for apex with google
Creating sub zero dashboard plugin for apex with googleCreating sub zero dashboard plugin for apex with google
Creating sub zero dashboard plugin for apex with google
 
Rxjs swetugg
Rxjs swetuggRxjs swetugg
Rxjs swetugg
 
Rxjs ngvikings
Rxjs ngvikingsRxjs ngvikings
Rxjs ngvikings
 
Using Change Streams to Keep Up with Your Data
Using Change Streams to Keep Up with Your DataUsing Change Streams to Keep Up with Your Data
Using Change Streams to Keep Up with Your Data
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projects
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015
 
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
 
Akka: Actor Design & Communication Technics
Akka: Actor Design & Communication TechnicsAkka: Actor Design & Communication Technics
Akka: Actor Design & Communication Technics
 
Controller specs
Controller specsController specs
Controller specs
 
Goal Based Data Production with Sim Simeonov
Goal Based Data Production with Sim SimeonovGoal Based Data Production with Sim Simeonov
Goal Based Data Production with Sim Simeonov
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of Control
 
Tweaking the interactive grid
Tweaking the interactive gridTweaking the interactive grid
Tweaking the interactive grid
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
201410 2 fiware-orion-contextbroker
201410 2 fiware-orion-contextbroker201410 2 fiware-orion-contextbroker
201410 2 fiware-orion-contextbroker
 
Automation in angular js
Automation in angular jsAutomation in angular js
Automation in angular js
 

Destaque

Shadow Techniques for Real-Time and Interactive Applications
Shadow Techniques for Real-Time and Interactive ApplicationsShadow Techniques for Real-Time and Interactive Applications
Shadow Techniques for Real-Time and Interactive Applications
stefan_b
 
Hageman id software project
Hageman id software projectHageman id software project
Hageman id software project
Adam Hageman
 
BSPTreesGameEngines-2
BSPTreesGameEngines-2BSPTreesGameEngines-2
BSPTreesGameEngines-2
Jason Calvert
 
BSPTreesGameEngines-1
BSPTreesGameEngines-1BSPTreesGameEngines-1
BSPTreesGameEngines-1
Jason Calvert
 

Destaque (14)

Data Synchronization Patterns in Mobile Application Design
Data Synchronization Patterns in Mobile Application DesignData Synchronization Patterns in Mobile Application Design
Data Synchronization Patterns in Mobile Application Design
 
AppSync.org: open-source patterns and code for data synchronization in mobile...
AppSync.org: open-source patterns and code for data synchronization in mobile...AppSync.org: open-source patterns and code for data synchronization in mobile...
AppSync.org: open-source patterns and code for data synchronization in mobile...
 
Offline first: application data and synchronization
Offline first: application data and synchronizationOffline first: application data and synchronization
Offline first: application data and synchronization
 
Sync is hard: building offline-first Android apps from the ground up
Sync is hard: building offline-first Android apps from the ground up	Sync is hard: building offline-first Android apps from the ground up
Sync is hard: building offline-first Android apps from the ground up
 
Offline First Applications
Offline First ApplicationsOffline First Applications
Offline First Applications
 
FITC presents: Mobile & offline data synchronization in Angular JS
FITC presents: Mobile & offline data synchronization in Angular JSFITC presents: Mobile & offline data synchronization in Angular JS
FITC presents: Mobile & offline data synchronization in Angular JS
 
Doom3
Doom3Doom3
Doom3
 
Shadow Techniques for Real-Time and Interactive Applications
Shadow Techniques for Real-Time and Interactive ApplicationsShadow Techniques for Real-Time and Interactive Applications
Shadow Techniques for Real-Time and Interactive Applications
 
Threading Game Engines: QUAKE 4 & Enemy Territory QUAKE Wars
Threading Game Engines: QUAKE 4 & Enemy Territory QUAKE WarsThreading Game Engines: QUAKE 4 & Enemy Territory QUAKE Wars
Threading Game Engines: QUAKE 4 & Enemy Territory QUAKE Wars
 
Beyond GPS - Neogeograpy Data Collection
Beyond GPS - Neogeograpy Data CollectionBeyond GPS - Neogeograpy Data Collection
Beyond GPS - Neogeograpy Data Collection
 
Hageman id software project
Hageman id software projectHageman id software project
Hageman id software project
 
[SEN#7] Le Top 100 des entreprises qui recrutent dans le numérique
[SEN#7] Le Top 100 des entreprises qui recrutent dans le numérique[SEN#7] Le Top 100 des entreprises qui recrutent dans le numérique
[SEN#7] Le Top 100 des entreprises qui recrutent dans le numérique
 
BSPTreesGameEngines-2
BSPTreesGameEngines-2BSPTreesGameEngines-2
BSPTreesGameEngines-2
 
BSPTreesGameEngines-1
BSPTreesGameEngines-1BSPTreesGameEngines-1
BSPTreesGameEngines-1
 

Semelhante a Implementing Server Side Data Synchronization for Mobile Apps

fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
Wesley Beary
 
Intravert Server side processing for Cassandra
Intravert Server side processing for CassandraIntravert Server side processing for Cassandra
Intravert Server side processing for Cassandra
Edward Capriolo
 
Live Streaming & Server Sent Events
Live Streaming & Server Sent EventsLive Streaming & Server Sent Events
Live Streaming & Server Sent Events
tkramar
 

Semelhante a Implementing Server Side Data Synchronization for Mobile Apps (20)

fog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloudfog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloud
 
Advanced redux
Advanced reduxAdvanced redux
Advanced redux
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
 
Intravert Server side processing for Cassandra
Intravert Server side processing for CassandraIntravert Server side processing for Cassandra
Intravert Server side processing for Cassandra
 
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
 
Going crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHPGoing crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHP
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015
 
DDDing Tools = Akka Persistence
DDDing Tools = Akka PersistenceDDDing Tools = Akka Persistence
DDDing Tools = Akka Persistence
 
Beyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the codeBeyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the code
 
Microsoft NERD Talk - R and Tableau - 2-4-2013
Microsoft NERD Talk - R and Tableau - 2-4-2013Microsoft NERD Talk - R and Tableau - 2-4-2013
Microsoft NERD Talk - R and Tableau - 2-4-2013
 
Nodejs Explained with Examples
Nodejs Explained with ExamplesNodejs Explained with Examples
Nodejs Explained with Examples
 
Nodejsexplained 101116115055-phpapp02
Nodejsexplained 101116115055-phpapp02Nodejsexplained 101116115055-phpapp02
Nodejsexplained 101116115055-phpapp02
 
Node.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community VijayawadaNode.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community Vijayawada
 
Grokking Engineering - Data Analytics Infrastructure at Viki - Huy Nguyen
Grokking Engineering - Data Analytics Infrastructure at Viki - Huy NguyenGrokking Engineering - Data Analytics Infrastructure at Viki - Huy Nguyen
Grokking Engineering - Data Analytics Infrastructure at Viki - Huy Nguyen
 
Books
BooksBooks
Books
 
Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...
Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...
Building and Incredible Machine with Pipelines and Generators in PHP (IPC Ber...
 
Server Side Events
Server Side EventsServer Side Events
Server Side Events
 
CGI.ppt
CGI.pptCGI.ppt
CGI.ppt
 
Akka persistence == event sourcing in 30 minutes
Akka persistence == event sourcing in 30 minutesAkka persistence == event sourcing in 30 minutes
Akka persistence == event sourcing in 30 minutes
 
Live Streaming & Server Sent Events
Live Streaming & Server Sent EventsLive Streaming & Server Sent Events
Live Streaming & Server Sent Events
 

Mais de Michele Orselli

Developing sustainable php projects
Developing sustainable php projectsDeveloping sustainable php projects
Developing sustainable php projects
Michele Orselli
 
Zend Framework 2 per chi viene da Symfony2
Zend Framework 2 per chi viene da Symfony2Zend Framework 2 per chi viene da Symfony2
Zend Framework 2 per chi viene da Symfony2
Michele Orselli
 

Mais de Michele Orselli (20)

Tackling Tech Debt with Rector
Tackling Tech Debt with RectorTackling Tech Debt with Rector
Tackling Tech Debt with Rector
 
Comunicare, condividere e mantenere decisioni architetturali nei team di svil...
Comunicare, condividere e mantenere decisioni architetturali nei team di svil...Comunicare, condividere e mantenere decisioni architetturali nei team di svil...
Comunicare, condividere e mantenere decisioni architetturali nei team di svil...
 
A dive into Symfony 4
A dive into Symfony 4A dive into Symfony 4
A dive into Symfony 4
 
A recommendation engine for your applications codemotion ams
A recommendation engine for your applications codemotion amsA recommendation engine for your applications codemotion ams
A recommendation engine for your applications codemotion ams
 
A recommendation engine for your applications phpday
A recommendation engine for your applications phpdayA recommendation engine for your applications phpday
A recommendation engine for your applications phpday
 
Hopping in clouds - phpuk 17
Hopping in clouds - phpuk 17Hopping in clouds - phpuk 17
Hopping in clouds - phpuk 17
 
A recommendation engine for your php application
A recommendation engine for your php applicationA recommendation engine for your php application
A recommendation engine for your php application
 
Symfony e micro (non così tanto) services
Symfony e micro (non così tanto) servicesSymfony e micro (non così tanto) services
Symfony e micro (non così tanto) services
 
Hopping in clouds: a tale of migration from one cloud provider to another
Hopping in clouds: a tale of migration from one cloud provider to anotherHopping in clouds: a tale of migration from one cloud provider to another
Hopping in clouds: a tale of migration from one cloud provider to another
 
Vagrant for real (codemotion rome 2016)
Vagrant for real (codemotion rome 2016)Vagrant for real (codemotion rome 2016)
Vagrant for real (codemotion rome 2016)
 
Vagrant for real codemotion (moar tips! ;-))
Vagrant for real codemotion (moar tips! ;-))Vagrant for real codemotion (moar tips! ;-))
Vagrant for real codemotion (moar tips! ;-))
 
Migrare a Symfony 3
Migrare a Symfony 3Migrare a Symfony 3
Migrare a Symfony 3
 
Vagrant for real
Vagrant for realVagrant for real
Vagrant for real
 
Continuous, continuous, continuous
Continuous, continuous, continuousContinuous, continuous, continuous
Continuous, continuous, continuous
 
Deploy a PHP App on Google App Engine
Deploy a PHP App on Google App EngineDeploy a PHP App on Google App Engine
Deploy a PHP App on Google App Engine
 
Deploy a php app on Google App Engine
Deploy a php app on Google App EngineDeploy a php app on Google App Engine
Deploy a php app on Google App Engine
 
Sf2 wtf
Sf2 wtfSf2 wtf
Sf2 wtf
 
Manage a project portfolio
Manage a project portfolioManage a project portfolio
Manage a project portfolio
 
Developing sustainable php projects
Developing sustainable php projectsDeveloping sustainable php projects
Developing sustainable php projects
 
Zend Framework 2 per chi viene da Symfony2
Zend Framework 2 per chi viene da Symfony2Zend Framework 2 per chi viene da Symfony2
Zend Framework 2 per chi viene da Symfony2
 

Último

introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
VishalKumarJha10
 

Último (20)

BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
Chinsurah Escorts ☎️8617697112 Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎️8617697112  Starting From 5K to 15K High Profile Escorts ...Chinsurah Escorts ☎️8617697112  Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎️8617697112 Starting From 5K to 15K High Profile Escorts ...
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
 
Pharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodologyPharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodology
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 

Implementing Server Side Data Synchronization for Mobile Apps

  • 1. Implementing Server Side Data Synchronization for Mobile Apps
  • 2. Michele Orselli CTO@Ideato ! _orso_ ! micheleorselli ! mo@ideato.it
  • 3. Agenda scenario design choices implementation alternative approaches
  • 4.
  • 5.
  • 7. Sync scenario A B C A B C A B C
  • 9. Scenario Brownfield project ! several mobile apps for tracking user generated data (calendar, notes, bio data) ! iOS & Android ! ~10 K users steadily growing at 1.2 K/month
  • 10. Scenario MongoDB ! Legacy App based on codeigniter ! Existing RPC-wannabe-REST API for data sync
  • 11. Scenario get updates: ! POST /m/<app>/get/<user_id>/<res>/<updated_from> ! ! ! send updates: ! POST /m/<app>/update/<user_id>/<res_id>/<dev_id>/<res> ! !
  • 12. api
  • 13. Scenario ! ! 6 different resources, 12 calls per sync ! apps sync by polling every 30 sec ! every call sync little data ! !
  • 14. Challenge ! ! rebuild sync API for old apps + 2 incoming ! allow image synchronization ! more efficient than previous API ! !
  • 15.
  • 16. Existing Solutions Tstamps, Vector clocks, CRDTs syncML, syncano Algorithms Protocols/API Azure Data sync Platform couchDB, riak Storage
  • 17. Not Invented Here? Don't Reinvent The Wheel, Unless You Plan on Learning More About Wheels ! J. Atwood
  • 18. Architecture ! ! 2 different mobile platforms several teams with different skill level ! changing storage wasn’t an option forcing a particular technology client side wasn’t an option
  • 19. Architecture c1 server c2 c3 sync logic conflicts resolution thin clients
  • 20. Implementation ! ! In the sync domain all resources are the same ! For every app one endpoint for getting new data one endpoint for pushing changes one endpoint for uploading images
  • 21. Get changes ! Get all changes (1st sync): ! GET /apps/{app}/users/{user_id}/changes ! Get latest changes: ! GET /apps/{app}/users/{user_id}/changes?from={from}
  • 22. Get changes ! Get all changes (1st sync): ! GET /apps/{app}/users/{user_id}/changes ! Get latest changes: ! GET /apps/{app}/users/{user_id}/changes?from={from} timestamp?
  • 23. Server suggest the sync time timestamp are inaccurate (skew and developer errors) ! server suggests the “from” parameter to be used in the next request GET /changes c1 server { ‘next’ : 123456, ‘data’: […] }
  • 24. Server suggest the sync time GET /changes { ‘next’ : 12345, ‘data’: […] } c1 server
  • 25. Server suggest the sync time GET /changes { ‘next’ : 12345, ‘data’: […] } c1 server GET /changes?from=12345 { ‘next’ : 45678, ‘data’: […] }
  • 26. what to transfer operations: {‘op’: ’add’, id: ‘1’, ’data’:[…]} {‘op’: ’update’, id: ‘1’, ’data’:[…]} {‘op’: ’delete’, id: ‘1’} {‘op’: ’add’, id: ‘2’, ’data’:[…]} ! ! states: {id: ‘1’, ’data’:[…]} {id: 2’, ’data’:[…]} {id: ‘3’, ’data’:[…]}
  • 27. what to transfer ! we chosen to transfer states {id: ‘1’, ’type’: ‘measure’, ‘_deleted’: true} {id: 2’, ‘type’: ‘note’} {id: ‘3’, ‘type’: ‘note’} ! ! ps: soft delete all the things!
  • 28. unique identifiers How do we generate an unique id in a distributed system? ! UUID: several implementations (RFC 4122) ! Local Ids/Global Id: server generates GUIDs clients use local ids to manage their records GET /changes c1 server {‘data’:{’guid’: ‘58f0bdd7-1481’}}
  • 29. unique identifiers POST /merge { ‘data’: [ {’lid’: ‘1’, …}, {‘lid’: ‘2’, …} ] } c1 server { ‘data’: [ {‘guid’: ‘58f0bdd7-1400’, ’lid’: ‘1’, …}, {‘guid’: ‘6f9f3ec9-1400’, ‘lid’: ‘2’, …} ] }
  • 30. conflict resolution algorithm (plain data) ! server handles conflicts resolution mobile generated data are “temporary” until sync to server ! conflict resolution: domain indipendent: last-write wins domain dipendent: use domain knowledge to resolve
  • 31. conflict resolution algorithm (plain data) function sync($data) {! ! ! foreach ($data as $newRecord) {! ! ! ! $s = findByGuid($newRecord->getGuid());! ! ! ! ! if (!$s) {! ! ! ! add($newRecord);! ! ! ! send($newRecord);! ! ! ! continue;! ! ! }! ! ! ! ! ! ! if ($newRecord->updated > $s->updated) {! ! ! ! update($s, $newRecord);! ! ! ! send($newRecord);! ! ! ! continue;! ! ! }! ! ! ! ! ! updateRemote($newRecord, $s);! }
  • 32. conflict resolution algorithm (plain data) function sync($data) {! ! ! foreach ($data as $newRecord) {! ! ! ! $s = findByGuid($newRecord->getGuid());! ! ! ! ! if (!$s) {! ! ! ! add($newRecord);! ! ! ! send($newRecord);! ! ! ! continue;! ! ! }! ! ! ! ! ! ! if ($newRecord->updated > $s->updated) {! ! ! ! update($s, $newRecord);! ! ! ! send($newRecord);! ! ! ! continue;! ! ! }! ! ! ! ! ! updateRemote($newRecord, $s);! }
  • 33. conflict resolution algorithm (plain data) function sync($data) {! ! ! foreach ($data as $newRecord) {! ! ! ! $s = findByGuid($newRecord->getGuid());! ! ! ! ! if (!$s) {! ! ! ! add($newRecord);! ! ! ! send($newRecord);! ! ! ! continue;! ! ! }! ! ! ! ! ! ! if ($newRecord->updated > $s->updated) {! ! ! ! update($s, $newRecord);! ! ! ! send($newRecord);! ! ! ! continue;! ! ! }! ! ! ! ! ! updateRemote($newRecord, $s);! } no conflict
  • 34. conflict resolution algorithm (plain data) function sync($data) {! ! ! foreach ($data as $newRecord) {! ! ! ! $s = findByGuid($newRecord->getGuid());! ! ! ! ! if (!$s) {! ! ! ! add($newRecord);! ! ! ! send($newRecord);! ! ! ! continue;! ! ! }! ! ! ! ! ! ! if ($newRecord->updated > $s->updated) {! ! ! ! update($s, $newRecord);! ! ! ! send($newRecord);! ! ! ! continue;! ! ! }! ! ! ! ! ! updateRemote($newRecord, $s);! } remote wins
  • 35. conflict resolution algorithm (plain data) function sync($data) {! ! ! foreach ($data as $newRecord) {! ! ! ! $s = findByGuid($newRecord->getGuid());! ! ! ! ! if (!$s) {! ! ! ! add($newRecord);! ! ! ! send($newRecord);! ! ! ! continue;! ! ! }! ! ! ! ! ! ! if ($newRecord->updated > $s->updated) {! ! ! ! update($s, $newRecord);! ! ! ! send($newRecord);! ! ! ! continue;! ! ! }! ! ! ! ! ! updateRemote($newRecord, $s);! } server wins
  • 36. conflict resolution algorithm (plain data) { ‘lid’: ‘1’, ‘guid’: ‘af54d’, ‘data’ : ‘AAA’ ‘updated’: ’100’ } { ‘lid’: ‘2’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } c1 { ’guid’: ‘af54d’, ‘data’: ‘BBB’, ‘updated’ : ’20’ } server
  • 37. conflict resolution algorithm (plain data) { ‘lid’: ‘1’, ‘guid’: ‘af54d’, ‘data’ : ‘AAA’ ‘updated’: ’100’ } { ‘lid’: ‘2’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } POST /merge { ’guid’: ‘af54d’, ‘data’: ‘BBB’, ‘updated’ : ’20’ } c1 server
  • 38. conflict resolution algorithm (plain data) { ‘lid’: ‘1’, ‘guid’: ‘af54d’, ‘data’ : ‘AAA’ ‘updated’: ’100’ } { ‘lid’: ‘2’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } POST /merge { ‘guid’: ‘e324f’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } { ’guid’: ‘af54d’, ‘data’: ‘BBB’, ‘updated’ : ’20’ } c1 server
  • 39. conflict resolution algorithm (plain data) { ‘lid’: ‘1’, ‘guid’: ‘af54d’, ‘data’ : ‘AAA’ ‘updated’: ’100’ } { ‘lid’: ‘2’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } POST /merge { ‘guid’: ‘e324f’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } { ’guid’: ‘af54d’, ‘data’: ‘BBB’, ‘updated’ : ’20’ } c1 server
  • 40. conflict resolution algorithm (plain data) { ‘lid’: ‘1’, ‘guid’: ‘af54d’, ‘data’ : ‘AAA’ ‘updated’: ’100’ } { ‘lid’: ‘2’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } POST /merge { ‘guid’: ‘e324f’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } { ’guid’: ‘af54d’, ‘data’: ‘AAA’, ‘updated’ : ’100’ } c1 server
  • 41. conflict resolution algorithm (plain data) { ‘lid’: ‘1’, ‘guid’: ‘af54d’, ‘data’ : ‘AAA’ ‘updated’: ’100’ } { ‘guid’: ‘e324f’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } { ’guid’: ‘af54d’, ‘data’: ‘AAA’, ‘updated’ : ’100’ } { ‘lid’: ‘2’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } POST /merge c1 server {‘ok’ : { ’guid’: ‘af54d’ }} {‘update’ : { lid: ‘2’, ’guid’: ‘e324f’ }}
  • 42. conflict resolution algorithm (hierarchical data) ! How to manage hierarchical data? ! ! { ‘lid’ : ‘123456’, ‘type’ : ‘baby’, … } { ‘lid’ : ‘123456’, ‘type’ : ‘temperature’, ‘baby_id : ‘123456’ }
  • 43. conflict resolution algorithm (hierarchical data) ! How to manage hierarchical data? 1) sync root record 2) update ids 3) sync child records ! ! { ‘lid’ : ‘123456’, ‘type’ : ‘baby’, … } { ‘lid’ : ‘123456’, ‘type’ : ‘temperature’, ‘baby_id : ‘123456’ }
  • 44. conflict resolution algorithm (hierarchical data) function syncHierarchical($data) {! ! ! sortByHierarchy($data);! ! ! foreach ($data as $newRootRecord) {! ! ! ! ! ! $s = findByGuid($newRootRecord->getGuid());! ! ! ! ! ! if($newRecord->isRoot()) {! ! ! ! ! if (!$s) {! ! ! ! ! add($newRootRecord);! ! ! ! ! updateRecordIds($newRootRecord, $data);! ! ! ! ! send($newRootRecord);! ! ! ! ! continue;! ! ! ! }! ! ! ! ! ! ! ! …
  • 45. conflict resolution algorithm (hierarchical data) function syncHierarchical($data) {! ! ! sortByHierarchy($data);! parent records first ! ! foreach ($data as $newRootRecord) {! ! ! ! ! ! $s = findByGuid($newRootRecord->getGuid());! ! ! ! ! ! if($newRecord->isRoot()) {! ! ! ! ! if (!$s) {! ! ! ! ! add($newRootRecord);! ! ! ! ! updateRecordIds($newRootRecord, $data);! ! ! ! ! send($newRootRecord);! ! ! ! ! continue;! ! ! ! }! ! ! ! ! ! ! ! …
  • 46. conflict resolution algorithm (hierarchical data) function syncHierarchical($data) {! ! ! sortByHierarchy($data);! ! ! foreach ($data as $newRootRecord) {! ! ! ! ! ! $s = findByGuid($newRootRecord->getGuid());! ! ! ! ! ! if($newRecord->isRoot()) {! ! ! ! ! if (!$s) {! ! ! ! ! add($newRootRecord);! ! ! ! ! updateRecordIds($newRootRecord, $data);! ! ! ! ! send($newRootRecord);! ! ! ! ! continue;! ! ! ! }! ! ! ! ! ! ! ! …
  • 47. conflict resolution algorithm (hierarchical data) function syncHierarchical($data) {! ! ! sortByHierarchy($data);! ! ! foreach ($data as $newRootRecord) {! ! ! ! ! ! $s = findByGuid($newRootRecord->getGuid());! ! ! ! ! ! if($newRecord->isRoot()) {! ! ! ! ! if (!$s) {! ! ! ! ! add($newRootRecord);! ! ! ! ! updateRecordIds($newRootRecord, $data);! ! ! ! ! send($newRootRecord);! ! ! ! ! continue;! ! ! ! }! ! ! ! ! ! ! ! … no conflict
  • 48. conflict resolution algorithm (hierarchical data) ! ! ! …! ! ! ! ! ! if ($newRootRecord->updated > $s->updated) {! ! ! ! ! ! ! update($s, $newRecord);! ! ! ! updateRecordIds($newRootRecord, $data);! ! ! ! ! ! send($newRootRecord);! ! ! ! continue;! ! ! } else {! ! ! ! updateRecordIds($s, $data);! ! ! ! updateRemote($newRecord, $s);! ! ! }! ! ! } else {! ! ! sync($data);! ! }! ! }! remote wins
  • 49. conflict resolution algorithm (hierarchical data) ! ! ! …! ! ! ! ! ! if ($newRootRecord->updated > $s->updated) {! ! ! ! ! ! ! update($s, $newRecord);! ! ! ! updateRecordIds($newRootRecord, $data);! ! ! ! ! ! send($newRootRecord);! ! ! ! continue;! ! ! } else {! ! ! ! updateRecordIds($s, $data);! server wins ! ! ! updateRemote($newRecord, $s);! ! ! }! ! ! } else {! ! ! sync($data);! ! }! ! }!
  • 50. conflict resolution algorithm (hierarchical data) { ‘lid’: ‘1’, ‘data’ : ‘AAA’ ‘updated’: ’100’ } { ‘lid’: ‘2’, ‘parent’: ‘1’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } POST /merge c1 server
  • 51. conflict resolution algorithm (hierarchical data) { ‘lid’: ‘1’, ‘data’ : ‘AAA’ ‘updated’: ’100’ } { ‘lid’: ‘2’, ‘parent’: ‘1’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } c1 server POST /merge { ‘lid’: ‘1’, ‘guid’ : ‘32ead’, ‘data’ : ‘AAA’ ‘updated’: ’100’ }
  • 52. conflict resolution algorithm (hierarchical data) { ‘lid’: ‘1’, ‘data’ : ‘AAA’ ‘updated’: ’100’ } { ‘lid’: ‘2’, ‘parent’: ‘32ead’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } c1 server POST /merge { ‘lid’: ‘1’, ‘guid’ : ‘32ead’, ‘data’ : ‘AAA’ ‘updated’: ’100’ }
  • 53. conflict resolution algorithm (hierarchical data) { ‘lid’: ‘1’, ‘data’ : ‘AAA’ ‘updated’: ’100’ } { ‘lid’: ‘2’, ‘parent’: ‘32ead’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } c1 server POST /merge { ‘lid’: ‘1’, ‘guid’ : ‘32ead’, ‘data’ : ‘AAA’ ‘updated’: ’100’ } { ‘lid’: ‘2’, ‘parent’: ‘32ead’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } {‘update’ : { ‘lid’: ‘1’, ’guid’: ‘af54d’ }} {‘update’ : { lid: ‘2’, ’guid’: ‘e324f’ }}
  • 54. enforcing domain constraints ! ! e.g. “only one temperature can be registered in a given day” ! how to we enforce domain constraints on data?
  • 55. enforcing domain constraints ! ! e.g. “only one temperature can be registered in a given day” ! how to we enforce domain constraints on data? 1) relax constraints
  • 56. enforcing domain constraints ! ! e.g. “only one temperature can be registered in a given day” ! how to we enforce domain constraints on data? 1) relax constraints 2) integrate constraints in sync algorithm
  • 57. ! ! from findByGuid to findSimilar ! first lookup by GUID then by domain rules ! “two measures are similar if are referred to the same date” ! ! ! ! enforcing domain constraints
  • 59. enforcing domain constraints { ’guid’: ‘af54d’, ‘when’: ‘20141005’ } c1 server
  • 60. enforcing domain constraints { ‘lid’: ‘1’, ‘when’: ‘20141005’ } { ’guid’: ‘af54d’, ‘when’: ‘20141005’ } c1 server
  • 61. enforcing domain constraints { ‘lid’: ‘1’, ‘when’: ‘20141005’ } { ’guid’: ‘af54d’, ‘when’: ‘20141005’ } POST /merge c1 server
  • 62. enforcing domain constraints { ‘lid’: ‘1’, ‘when’: ‘20141005’ } { ’guid’: ‘af54d’, ‘when’: ‘20141005’ } POST /merge c1 server
  • 63. enforcing domain constraints { ‘lid’: ‘1’, ‘when’: ‘20141005’ } { ’guid’: ‘af54d’, ‘when’: ‘20141005’ } POST /merge c1 server { ’guid’: ‘af54d’, ‘when’: ‘20141005’ }
  • 64. dealing with binary data ! Binary data uploaded via custom endpoint ! Sync data remain small ! Uploads can be resumed
  • 65. dealing with binary data ! Two steps* 1) data are synched to server 2) related images are uploaded ! * this means record without file for a given time
  • 66. dealing with binary data POST /merge { ‘lid’ : 1, ‘type’ : ‘baby’, ‘image’ : ‘myimage.jpg’ } { ‘lid’ : 1, ‘guid’ : ‘ac435-f8345’ } c1 server POST /upload/ac435-f8345/image
  • 67. What we learned ! Implementing this stuff is tricky ! Explore existing solution if you can ! Understanding the domain is important
  • 69. CRDT ! Conflict-free Replicated Data Types (CRDTs) ! Constraining the types of operations in order to: - ensure convergence of changes to shared data by uncoordinated, concurrent actors - eliminate network failure modes as a source of error
  • 70. Math!!! CRDT ! Bounded-join semilattices - join operation defining a least upper bound - partially order set - always increasing
  • 71. Gateways handles sync Data flows through channels - partition data set - authorization - limit the data ! Use revision trees Couchbase Mobile
  • 72. Riak Distributed DB Eventually/Strong Consistency ! Data Types ! Configurable conflic resolution - db level for built-in data types - application level for custom data
  • 73. ! That’s all folks! Questions? ! Please leave feedback! https://joind.in/11797 !
  • 74. Links Vector Clocks http://basho.com/why-vector-clocks-are-easy/ http://www.datastax.com/dev/blog/why-cassandra-doesnt-need-vector-clocks http://basho.com/why-vector-clocks-are-hard/ ! CRDTs http://christophermeiklejohn.com/distributed/systems/2013/07/12/readings-in-distributed-systems. html http://www.infoq.com/presentations/problems-distributed-systems https://www.youtube.com/watch?v=qyVNG7fnubQ ! Riak http://docs.basho.com/riak/latest/dev/using/conflict-resolution/ ! Couchbase Sync Gateway http://docs.couchbase.com/sync-gateway/ http://www.infoq.com/presentations/sync-mobile-data ! API http://developers.amiando.com/index.php/REST_API_DataSync https://login.syncano.com/docs/rest/index.html
  • 75. Credits phones https://www.flickr.com/photos/15216811@N06/14504964841 wat http://uturncrossfit.com/wp-content/uploads/2014/04/wait-what.jpg darth http://www.listal.com/viewimage/3825918h blueprint: http://upload.wikimedia.org/wikipedia/commons/5/5e/Joy_Oil_gas_station_blueprints.jpg! building: http://s0.geograph.org.uk/geophotos/02/42/74/2427436_96c4cd84.jpg! brownfield: http://s0.geograph.org.uk/geophotos/02/04/54/2045448_03a2fb36.jpg! no connection: https://www.flickr.com/photos/77018488@N03/9004800239! no internet con https://www.flickr.com/photos/roland/9681237793! vector clocks: http://en.wikipedia.org/wiki/Vector_clock! crdts: http://www.infoq.com/presentations/problems-distributed-systems