SlideShare uma empresa Scribd logo
1 de 99
Baixar para ler offline
Implementing data 
synchronization API for 
mobile apps with Silex
Michele Orselli 
CTO@Ideato 
_orso_ 
micheleorselli / ideatosrl 
mo@ideato.it
Agenda 
scenario design choices 
implementation alternative approaches
Server side data sync for mobile apps with silex
Server side data sync for mobile apps with silex
Sync scenario 
A 
B 
C
Sync scenario 
ABC 
ABC 
ABC
Dealing with conflicts 
A1 
A2 
?
Brownfield project 
Scenario 
several mobile apps for tracking user generated 
data (calendar, notes, bio data) 
iOS & Android 
~10 K users steadily growing at 1.2 K/month
MongoDB 
Scenario 
Legacy App based on Codeigniter 
Existing RPC-wannabe-REST API for data sync
For every resource 
get updates: 
Scenario 
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 
Enable image synchronization 
More efficient than previous API
Server side data sync for mobile apps with silex
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 managed in 
the same way
Implementation 
For every app: 
one endpoint for getting new data 
one endpoint for pushing changes 
one endpoint for uploading images
The new APIs 
GET /apps/:app/users/:user_id/changes[?from=:from] 
POST /apps/:app/users/:user_id/merge 
POST /upload/:res_id/images
Silex Implementation
Silex Implementation 
Col 1 
Col 2 
Col 3
Silex Implementation 
Col 1 
Col 2 
Col 3 
Sync Service
Silex Implementation 
Col 1 
Col 2 
Col 3 
Sync Service
Silex Implementation 
Col 1 
Col 2 
Col 3 
Sync Service
Silex Implementation 
Col 1 
Col 2 
Col 3 
Sync Service
Silex Implementation 
Col 1 
Col 2 
Col 3 
Sync Service
Silex Implementation 
Col 1 
Col 2 
Col 3 
Sync Service
Silex Implementation 
Col 1 
Col 2 
Col 3 
Sync Service
Silex Implementation 
$app->get(“/apps/{mApp}/users/{userId}/changes”, 
function ($mApp, $userId, $app, $request) 
{ 
$lastSync = $request->get('from', null); 
$syncService = $app[‘syncService’]; 
$syncService->sync($lastSync, $userId); 
$response = new JsonResponse( 
$syncService->getResult() 
); 
return $response; 
}
Silex Implementation 
$app->get(“/apps/{mApp}/users/{userId}/changes”, 
function ($mApp, $userId, $app, $request) 
{ 
$lastSync = $request->get('from', null); 
$syncService = $app[‘syncService’]; 
$syncService->sync($lastSync, $userId); 
$response = new JsonResponse( 
$syncService->getResult() 
); 
return $response; 
}
Silex Implementation 
$app->get(“/apps/{mApp}/users/{userId}/changes”, 
function ($mApp, $userId, $app, $request) 
{ 
$lastSync = $request->get('from', null); 
$syncService = $app[‘syncService’]; 
$syncService->sync($lastSync, $userId); 
$response = new JsonResponse( 
$syncService->getResult() 
); 
return $response; 
}
Silex Implementation 
$app->get(“/apps/{mApp}/users/{userId}/changes”, 
function ($mApp, $userId, $app, $request) 
{ 
$lastSync = $request->get('from', null); 
$syncService = $app[‘syncService’]; 
$syncService->sync($lastSync, $userId); 
$response = new JsonResponse( 
$syncService->getResult() 
); 
return $response; 
}
Silex Implementation 
$app->get(“/apps/{mApp}/users/{userId}/merge”, 
function ($mApp, $userId, $app, $request) 
{ 
$lastSync = $request->get('from', null); 
$data = $request->get(‘data’, false); 
$syncService = $app[‘syncService’]; 
$syncService->merge($data, $lastSync, $userId); 
$response = new JsonResponse( 
$syncService->getResult() 
); 
return $response; 
}
Silex Implementation 
$app->get(“/apps/{mApp}/users/{userId}/merge”, 
function ($mApp, $userId, $app, $request) 
{ 
$lastSync = $request->get('from', null); 
$data = $request->get(‘data’, false); 
$syncService = $app[‘syncService’]; 
$syncService->merge($data, $lastSync, $userId); 
$response = new JsonResponse( 
$syncService->getResult() 
); 
return $response; 
}
Silex Implementation 
$app->get(“/apps/{mApp}/users/{userId}/merge”, 
function ($mApp, $userId, $app, $request) 
{ 
$lastSync = $request->get('from', null); 
$data = $request->get(‘data’, false); 
$syncService = $app[‘syncService’]; 
$syncService->merge($data, $lastSync, $userId); 
$response = new JsonResponse( 
$syncService->getResult() 
); 
return $response; 
}
Silex Implementation 
$app->get(“/apps/{mApp}/users/{userId}/merge”, 
function ($mApp, $userId, $app, $request) 
{ 
$lastSync = $request->get('from', null); 
$data = $request->get(‘data’, false); 
$syncService = $app[‘syncService’]; 
$syncService->merge($data, $lastSync, $userId); 
$response = new JsonResponse( 
$syncService->getResult() 
); 
return $response; 
}
Silex Implementation 
$app->get(“/apps/{mApp}/users/{userId}/merge”, 
function ($mApp, $userId, $app, $request) 
{ 
$lastSync = $request->get('from', null); 
$data = $request->get(‘data’, false); 
$syncService = $app[‘syncService’]; 
$syncService->merge($data, $lastSync, $userId); 
$response = new JsonResponse( 
$syncService->getResult() 
); 
return $response; 
}
Silex Implementation 
$app['mongodb'] = new MongoDb(…); 
$app[‘changesRepo’] = new ChangesRepository( 
$app[‘mongodb’] 
); 
$app[‘syncService’] ? new SyncService( 
$app[‘changesRepo’] 
);
Get changes 
GET /apps/:app/users/:user_id/changes?from=:from 
timestamp?
Server suggest the sync time 
timestamp are inaccurate 
server suggests the “from” parameter to be used 
in the next request
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’: […] }
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
what to transfer 
we choose 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?
unique identifiers 
How do we generate an unique id in a distributed 
system? 
UUID (RFC 4122): several implementations in PHP 
(https://github.com/ramsey/uuid)
unique identifiers 
How do we generate an unique id in a distributed 
system? 
Local/Global Id: only the server generates GUIDs 
clients use local ids to manage their records
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) 
mobile generated data are “temporary” until sync 
to server 
server handles conflicts resolution
conflict resolution algorithm (plain data) 
conflict resolution: 
domain indipendent: e.g. last-write wins 
domain dipendent: use domain knowledge to 
resolve
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); 
} 
conflict resolution algorithm (plain data) 
no conflict
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) 
remote wins
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) 
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); 
foreach ($data as $newRootRecord) { 
$s = findByGuid($newRootRecord->getGuid()); 
if($newRecord->isRoot()) { 
if (!$s) { 
add($newRootRecord); 
updateRecordIds($newRootRecord, $data); 
send($newRootRecord); 
continue; 
} 
… 
parent records first
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
… 
if ($newRootRecord->updated > $s->updated) { 
update($s, $newRecord); 
updateRecordIds($newRootRecord, $data); 
send($newRootRecord); 
continue; 
} else { 
updateRecordIds($s, $data); 
updateRemote($newRecord, $s); 
} 
} else { 
sync($data); 
} 
} 
conflict resolution algorithm (hierarchical data) 
remote wins
… 
if ($newRootRecord->updated > $s->updated) { 
update($s, $newRecord); 
updateRecordIds($newRootRecord, $data); 
send($newRootRecord); 
continue; 
} else { 
updateRecordIds($s, $data); 
updateRemote($newRecord, $s); 
} 
} else { 
sync($data); 
} 
} 
conflict resolution algorithm (hierarchical data) 
server wins
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
enforcing domain constraints 
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 
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 remains small 
Uploads can be resumed
dealing with binary data 
Two steps* 
1) data are synchronized 
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
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
Couchbase Mobile 
Gateways handles sync 
Data flows through channels 
- partition data set 
- authorization 
- limit the data 
Use revision trees
Riak 
Distributed DB 
Eventually/Strong Consistency 
Data Types 
Configurable conflict resolution 
- db level for built-in data types 
- application level for custom 
data
That’s all folks! 
Questions? 
Please leave feedback! https://joind.in/12959
http://www.objc.io/issue-10/sync-case-study.html 
http://www.objc.io/issue-10/data-synchronization.html 
https://dev.evernote.com/media/pdf/edam-sync.pdf 
http://blog.helftone.com/clear-in-the-icloud/ 
http://strongloop.com/strongblog/node-js-replication-mobile-offline-sync-loopback/ 
http://blog.denivip.ru/index.php/2014/04/data-syncing-in-core-data-based-ios-apps/?lang=en 
http://inessential.com/2014/02/15/vesper_sync_diary_8_the_problem_of_un 
http://culturedcode.com/things/blog/2010/12/state-of-sync-part-1.html 
http://programmers.stackexchange.com/questions/206310/data-synchronization-in-mobile-apps-multiple- 
devices-multiple-users 
http://bricklin.com/offline.htm 
http://blog.couchbase.com/why-mobile-sync 
Links
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/ 
http://blog.8thlight.com/rylan-dirksen/2013/10/04/synchronization-in-a-distributed-system.html 
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

Developing A Real World Logistic Application With Oracle Application - UKOUG ...
Developing A Real World Logistic Application With Oracle Application - UKOUG ...Developing A Real World Logistic Application With Oracle Application - UKOUG ...
Developing A Real World Logistic Application With Oracle Application - UKOUG ...Roel Hartman
 
Bringing Transactional Guarantees to MongoDB
Bringing Transactional Guarantees to MongoDBBringing Transactional Guarantees to MongoDB
Bringing Transactional Guarantees to MongoDBPaul Robinson
 
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 BebopJSFestUA
 
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'sRoel Hartman
 
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 googleRoel Hartman
 
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 extensionLINE Corporation
 
Akka: Actor Design & Communication Technics
Akka: Actor Design & Communication TechnicsAkka: Actor Design & Communication Technics
Akka: Actor Design & Communication TechnicsAlex Fruzenshtein
 
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...Codemotion
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of ControlChad Hietala
 
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)Dan Robinson
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projectsIgnacio Martín
 
201410 2 fiware-orion-contextbroker
201410 2 fiware-orion-contextbroker201410 2 fiware-orion-contextbroker
201410 2 fiware-orion-contextbrokerFIWARE
 
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 DataMongoDB
 
Bare-knuckle web development
Bare-knuckle web developmentBare-knuckle web development
Bare-knuckle web developmentJohannes Brodwall
 
Tweaking the interactive grid
Tweaking the interactive gridTweaking the interactive grid
Tweaking the interactive gridRoel Hartman
 
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 SimeonovDatabricks
 

Mais procurados (20)

Developing A Real World Logistic Application With Oracle Application - UKOUG ...
Developing A Real World Logistic Application With Oracle Application - UKOUG ...Developing A Real World Logistic Application With Oracle Application - UKOUG ...
Developing A Real World Logistic Application With Oracle Application - UKOUG ...
 
Bringing Transactional Guarantees to MongoDB
Bringing Transactional Guarantees to MongoDBBringing Transactional Guarantees to MongoDB
Bringing Transactional Guarantees to MongoDB
 
React lecture
React lectureReact lecture
React lecture
 
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
 
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
 
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
 
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
 
Akka: Actor Design & Communication Technics
Akka: Actor Design & Communication TechnicsAkka: Actor Design & Communication Technics
Akka: Actor Design & Communication Technics
 
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
 
Rxjs swetugg
Rxjs swetuggRxjs swetugg
Rxjs swetugg
 
Rxjs ngvikings
Rxjs ngvikingsRxjs ngvikings
Rxjs ngvikings
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of Control
 
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)
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projects
 
Controller specs
Controller specsController specs
Controller specs
 
201410 2 fiware-orion-contextbroker
201410 2 fiware-orion-contextbroker201410 2 fiware-orion-contextbroker
201410 2 fiware-orion-contextbroker
 
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
 
Bare-knuckle web development
Bare-knuckle web developmentBare-knuckle web development
Bare-knuckle web development
 
Tweaking the interactive grid
Tweaking the interactive gridTweaking the interactive grid
Tweaking the interactive grid
 
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
 

Destaque

PHP Experience 2016 - [Palestra] Scaling with Microservice
PHP Experience 2016 - [Palestra] Scaling with MicroservicePHP Experience 2016 - [Palestra] Scaling with Microservice
PHP Experience 2016 - [Palestra] Scaling with MicroserviceiMasters
 
Building a-self-sufficient-team
Building a-self-sufficient-teamBuilding a-self-sufficient-team
Building a-self-sufficient-teamFilippo De Santis
 
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) servicesMichele Orselli
 
Exposing M2M to the REST of us
Exposing M2M to the REST of usExposing M2M to the REST of us
Exposing M2M to the REST of usMatteo Collina
 
Vagrant for real (codemotion rome 2016)
Vagrant for real (codemotion rome 2016)Vagrant for real (codemotion rome 2016)
Vagrant for real (codemotion rome 2016)Michele Orselli
 
Dependency Management with Composer
Dependency Management with ComposerDependency Management with Composer
Dependency Management with ComposerJordi Boggiano
 

Destaque (6)

PHP Experience 2016 - [Palestra] Scaling with Microservice
PHP Experience 2016 - [Palestra] Scaling with MicroservicePHP Experience 2016 - [Palestra] Scaling with Microservice
PHP Experience 2016 - [Palestra] Scaling with Microservice
 
Building a-self-sufficient-team
Building a-self-sufficient-teamBuilding a-self-sufficient-team
Building a-self-sufficient-team
 
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
 
Exposing M2M to the REST of us
Exposing M2M to the REST of usExposing M2M to the REST of us
Exposing M2M to the REST of us
 
Vagrant for real (codemotion rome 2016)
Vagrant for real (codemotion rome 2016)Vagrant for real (codemotion rome 2016)
Vagrant for real (codemotion rome 2016)
 
Dependency Management with Composer
Dependency Management with ComposerDependency Management with Composer
Dependency Management with Composer
 

Semelhante a Server side data sync for mobile apps with silex

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 2015Fernando Daciuk
 
AWS re:Invent 2016: Chalice: A Serverless Microframework for Python (DEV308)
AWS re:Invent 2016: Chalice: A Serverless Microframework for Python (DEV308)AWS re:Invent 2016: Chalice: A Serverless Microframework for Python (DEV308)
AWS re:Invent 2016: Chalice: A Serverless Microframework for Python (DEV308)Amazon Web Services
 
Nodejs do teste de unidade ao de integração
Nodejs  do teste de unidade ao de integraçãoNodejs  do teste de unidade ao de integração
Nodejs do teste de unidade ao de integraçãoVinícius Pretto da Silva
 
SharePoint Conference 2018 - APIs, APIs everywhere!
SharePoint Conference 2018 - APIs, APIs everywhere!SharePoint Conference 2018 - APIs, APIs everywhere!
SharePoint Conference 2018 - APIs, APIs everywhere!Sébastien Levert
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryTatsuhiko Miyagawa
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Elena Kolevska
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every dayVadym Khondar
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesLindsay Holmwood
 
Writing RESTful web services using Node.js
Writing RESTful web services using Node.jsWriting RESTful web services using Node.js
Writing RESTful web services using Node.jsFDConf
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From IusethisMarcus Ramberg
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & RESTHugo Hamon
 
SharePoint Saturday Belgium 2018 - APIs, APIs everywhere!
SharePoint Saturday Belgium 2018 - APIs, APIs everywhere!SharePoint Saturday Belgium 2018 - APIs, APIs everywhere!
SharePoint Saturday Belgium 2018 - APIs, APIs everywhere!Sébastien Levert
 
APIs, APIs Everywhere!
APIs, APIs Everywhere!APIs, APIs Everywhere!
APIs, APIs Everywhere!BIWUG
 
Make WordPress realtime.
Make WordPress realtime.Make WordPress realtime.
Make WordPress realtime.Josh Hillier
 

Semelhante a Server side data sync for mobile apps with silex (20)

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
 
AWS re:Invent 2016: Chalice: A Serverless Microframework for Python (DEV308)
AWS re:Invent 2016: Chalice: A Serverless Microframework for Python (DEV308)AWS re:Invent 2016: Chalice: A Serverless Microframework for Python (DEV308)
AWS re:Invent 2016: Chalice: A Serverless Microframework for Python (DEV308)
 
Advanced redux
Advanced reduxAdvanced redux
Advanced redux
 
Reduxing like a pro
Reduxing like a proReduxing like a pro
Reduxing like a pro
 
Nodejs do teste de unidade ao de integração
Nodejs  do teste de unidade ao de integraçãoNodejs  do teste de unidade ao de integração
Nodejs do teste de unidade ao de integração
 
SharePoint Conference 2018 - APIs, APIs everywhere!
SharePoint Conference 2018 - APIs, APIs everywhere!SharePoint Conference 2018 - APIs, APIs everywhere!
SharePoint Conference 2018 - APIs, APIs everywhere!
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websites
 
Complex Sites with Silex
Complex Sites with SilexComplex Sites with Silex
Complex Sites with Silex
 
Writing RESTful web services using Node.js
Writing RESTful web services using Node.jsWriting RESTful web services using Node.js
Writing RESTful web services using Node.js
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
 
REST API for your WP7 App
REST API for your WP7 AppREST API for your WP7 App
REST API for your WP7 App
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
 
SharePoint Saturday Belgium 2018 - APIs, APIs everywhere!
SharePoint Saturday Belgium 2018 - APIs, APIs everywhere!SharePoint Saturday Belgium 2018 - APIs, APIs everywhere!
SharePoint Saturday Belgium 2018 - APIs, APIs everywhere!
 
APIs, APIs Everywhere!
APIs, APIs Everywhere!APIs, APIs Everywhere!
APIs, APIs Everywhere!
 
Express JS
Express JSExpress JS
Express JS
 
Make WordPress realtime.
Make WordPress realtime.Make WordPress realtime.
Make WordPress realtime.
 

Mais de Michele Orselli

Tackling Tech Debt with Rector
Tackling Tech Debt with RectorTackling Tech Debt with Rector
Tackling Tech Debt with RectorMichele Orselli
 
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...Michele Orselli
 
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 amsMichele Orselli
 
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 phpdayMichele Orselli
 
Hopping in clouds - phpuk 17
Hopping in clouds - phpuk 17Hopping in clouds - phpuk 17
Hopping in clouds - phpuk 17Michele Orselli
 
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 applicationMichele Orselli
 
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 anotherMichele Orselli
 
Vagrant for real codemotion (moar tips! ;-))
Vagrant for real codemotion (moar tips! ;-))Vagrant for real codemotion (moar tips! ;-))
Vagrant for real codemotion (moar tips! ;-))Michele Orselli
 
Continuous, continuous, continuous
Continuous, continuous, continuousContinuous, continuous, continuous
Continuous, continuous, continuousMichele Orselli
 
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 EngineMichele Orselli
 
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 EngineMichele Orselli
 
Manage a project portfolio
Manage a project portfolioManage a project portfolio
Manage a project portfolioMichele Orselli
 
Developing sustainable php projects
Developing sustainable php projectsDeveloping sustainable php projects
Developing sustainable php projectsMichele 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 Symfony2Michele Orselli
 
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....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
 
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 (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
 
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
 
Extreme automation
Extreme automationExtreme automation
Extreme automation
 

Último

Kawika Technologies pvt ltd Software Development Company in Trivandrum
Kawika Technologies pvt ltd Software Development Company in TrivandrumKawika Technologies pvt ltd Software Development Company in Trivandrum
Kawika Technologies pvt ltd Software Development Company in TrivandrumKawika Technologies
 
ARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdf
ARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdfARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdf
ARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdfTobias Schneck
 
Why Choose Brain Inventory For Ecommerce Development.pdf
Why Choose Brain Inventory For Ecommerce Development.pdfWhy Choose Brain Inventory For Ecommerce Development.pdf
Why Choose Brain Inventory For Ecommerce Development.pdfBrain Inventory
 
online pdf editor software solutions.pdf
online pdf editor software solutions.pdfonline pdf editor software solutions.pdf
online pdf editor software solutions.pdfMeon Technology
 
Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...
Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...
Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...OnePlan Solutions
 
Deep Learning for Images with PyTorch - Datacamp
Deep Learning for Images with PyTorch - DatacampDeep Learning for Images with PyTorch - Datacamp
Deep Learning for Images with PyTorch - DatacampVICTOR MAESTRE RAMIREZ
 
Growing Oxen: channel operators and retries
Growing Oxen: channel operators and retriesGrowing Oxen: channel operators and retries
Growing Oxen: channel operators and retriesSoftwareMill
 
Your Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
Your Vision, Our Expertise: TECUNIQUE's Tailored Software TeamsYour Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
Your Vision, Our Expertise: TECUNIQUE's Tailored Software TeamsJaydeep Chhasatia
 
OpenChain Webinar: Universal CVSS Calculator
OpenChain Webinar: Universal CVSS CalculatorOpenChain Webinar: Universal CVSS Calculator
OpenChain Webinar: Universal CVSS CalculatorShane Coughlan
 
Watermarking in Source Code: Applications and Security Challenges
Watermarking in Source Code: Applications and Security ChallengesWatermarking in Source Code: Applications and Security Challenges
Watermarking in Source Code: Applications and Security ChallengesShyamsundar Das
 
How Does the Epitome of Spyware Differ from Other Malicious Software?
How Does the Epitome of Spyware Differ from Other Malicious Software?How Does the Epitome of Spyware Differ from Other Malicious Software?
How Does the Epitome of Spyware Differ from Other Malicious Software?AmeliaSmith90
 
Webinar_050417_LeClair12345666777889.ppt
Webinar_050417_LeClair12345666777889.pptWebinar_050417_LeClair12345666777889.ppt
Webinar_050417_LeClair12345666777889.pptkinjal48
 
Introduction-to-Software-Development-Outsourcing.pptx
Introduction-to-Software-Development-Outsourcing.pptxIntroduction-to-Software-Development-Outsourcing.pptx
Introduction-to-Software-Development-Outsourcing.pptxIntelliSource Technologies
 
Cybersecurity Challenges with Generative AI - for Good and Bad
Cybersecurity Challenges with Generative AI - for Good and BadCybersecurity Challenges with Generative AI - for Good and Bad
Cybersecurity Challenges with Generative AI - for Good and BadIvo Andreev
 
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.Sharon Liu
 
eAuditor Audits & Inspections - conduct field inspections
eAuditor Audits & Inspections - conduct field inspectionseAuditor Audits & Inspections - conduct field inspections
eAuditor Audits & Inspections - conduct field inspectionsNirav Modi
 
ERP For Electrical and Electronics manufecturing.pptx
ERP For Electrical and Electronics manufecturing.pptxERP For Electrical and Electronics manufecturing.pptx
ERP For Electrical and Electronics manufecturing.pptxAutus Cyber Tech
 
Generative AI for Cybersecurity - EC-Council
Generative AI for Cybersecurity - EC-CouncilGenerative AI for Cybersecurity - EC-Council
Generative AI for Cybersecurity - EC-CouncilVICTOR MAESTRE RAMIREZ
 
Big Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/ML
Big Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/MLBig Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/ML
Big Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/MLAlluxio, Inc.
 
IA Generativa y Grafos de Neo4j: RAG time
IA Generativa y Grafos de Neo4j: RAG timeIA Generativa y Grafos de Neo4j: RAG time
IA Generativa y Grafos de Neo4j: RAG timeNeo4j
 

Último (20)

Kawika Technologies pvt ltd Software Development Company in Trivandrum
Kawika Technologies pvt ltd Software Development Company in TrivandrumKawika Technologies pvt ltd Software Development Company in Trivandrum
Kawika Technologies pvt ltd Software Development Company in Trivandrum
 
ARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdf
ARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdfARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdf
ARM Talk @ Rejekts - Will ARM be the new Mainstream in our Data Centers_.pdf
 
Why Choose Brain Inventory For Ecommerce Development.pdf
Why Choose Brain Inventory For Ecommerce Development.pdfWhy Choose Brain Inventory For Ecommerce Development.pdf
Why Choose Brain Inventory For Ecommerce Development.pdf
 
online pdf editor software solutions.pdf
online pdf editor software solutions.pdfonline pdf editor software solutions.pdf
online pdf editor software solutions.pdf
 
Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...
Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...
Transforming PMO Success with AI - Discover OnePlan Strategic Portfolio Work ...
 
Deep Learning for Images with PyTorch - Datacamp
Deep Learning for Images with PyTorch - DatacampDeep Learning for Images with PyTorch - Datacamp
Deep Learning for Images with PyTorch - Datacamp
 
Growing Oxen: channel operators and retries
Growing Oxen: channel operators and retriesGrowing Oxen: channel operators and retries
Growing Oxen: channel operators and retries
 
Your Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
Your Vision, Our Expertise: TECUNIQUE's Tailored Software TeamsYour Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
Your Vision, Our Expertise: TECUNIQUE's Tailored Software Teams
 
OpenChain Webinar: Universal CVSS Calculator
OpenChain Webinar: Universal CVSS CalculatorOpenChain Webinar: Universal CVSS Calculator
OpenChain Webinar: Universal CVSS Calculator
 
Watermarking in Source Code: Applications and Security Challenges
Watermarking in Source Code: Applications and Security ChallengesWatermarking in Source Code: Applications and Security Challenges
Watermarking in Source Code: Applications and Security Challenges
 
How Does the Epitome of Spyware Differ from Other Malicious Software?
How Does the Epitome of Spyware Differ from Other Malicious Software?How Does the Epitome of Spyware Differ from Other Malicious Software?
How Does the Epitome of Spyware Differ from Other Malicious Software?
 
Webinar_050417_LeClair12345666777889.ppt
Webinar_050417_LeClair12345666777889.pptWebinar_050417_LeClair12345666777889.ppt
Webinar_050417_LeClair12345666777889.ppt
 
Introduction-to-Software-Development-Outsourcing.pptx
Introduction-to-Software-Development-Outsourcing.pptxIntroduction-to-Software-Development-Outsourcing.pptx
Introduction-to-Software-Development-Outsourcing.pptx
 
Cybersecurity Challenges with Generative AI - for Good and Bad
Cybersecurity Challenges with Generative AI - for Good and BadCybersecurity Challenges with Generative AI - for Good and Bad
Cybersecurity Challenges with Generative AI - for Good and Bad
 
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
20240319 Car Simulator Plan.pptx . Plan for a JavaScript Car Driving Simulator.
 
eAuditor Audits & Inspections - conduct field inspections
eAuditor Audits & Inspections - conduct field inspectionseAuditor Audits & Inspections - conduct field inspections
eAuditor Audits & Inspections - conduct field inspections
 
ERP For Electrical and Electronics manufecturing.pptx
ERP For Electrical and Electronics manufecturing.pptxERP For Electrical and Electronics manufecturing.pptx
ERP For Electrical and Electronics manufecturing.pptx
 
Generative AI for Cybersecurity - EC-Council
Generative AI for Cybersecurity - EC-CouncilGenerative AI for Cybersecurity - EC-Council
Generative AI for Cybersecurity - EC-Council
 
Big Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/ML
Big Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/MLBig Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/ML
Big Data Bellevue Meetup | Enhancing Python Data Loading in the Cloud for AI/ML
 
IA Generativa y Grafos de Neo4j: RAG time
IA Generativa y Grafos de Neo4j: RAG timeIA Generativa y Grafos de Neo4j: RAG time
IA Generativa y Grafos de Neo4j: RAG time
 

Server side data sync for mobile apps with silex

  • 1. Implementing data synchronization API for mobile apps with Silex
  • 2. Michele Orselli CTO@Ideato _orso_ micheleorselli / ideatosrl mo@ideato.it
  • 3. Agenda scenario design choices implementation alternative approaches
  • 9. Brownfield project Scenario 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. MongoDB Scenario Legacy App based on Codeigniter Existing RPC-wannabe-REST API for data sync
  • 11. For every resource get updates: Scenario 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 Enable image synchronization More efficient than previous API
  • 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 managed in the same way
  • 21. Implementation For every app: one endpoint for getting new data one endpoint for pushing changes one endpoint for uploading images
  • 22. The new APIs GET /apps/:app/users/:user_id/changes[?from=:from] POST /apps/:app/users/:user_id/merge POST /upload/:res_id/images
  • 24. Silex Implementation Col 1 Col 2 Col 3
  • 25. Silex Implementation Col 1 Col 2 Col 3 Sync Service
  • 26. Silex Implementation Col 1 Col 2 Col 3 Sync Service
  • 27. Silex Implementation Col 1 Col 2 Col 3 Sync Service
  • 28. Silex Implementation Col 1 Col 2 Col 3 Sync Service
  • 29. Silex Implementation Col 1 Col 2 Col 3 Sync Service
  • 30. Silex Implementation Col 1 Col 2 Col 3 Sync Service
  • 31. Silex Implementation Col 1 Col 2 Col 3 Sync Service
  • 32. Silex Implementation $app->get(“/apps/{mApp}/users/{userId}/changes”, function ($mApp, $userId, $app, $request) { $lastSync = $request->get('from', null); $syncService = $app[‘syncService’]; $syncService->sync($lastSync, $userId); $response = new JsonResponse( $syncService->getResult() ); return $response; }
  • 33. Silex Implementation $app->get(“/apps/{mApp}/users/{userId}/changes”, function ($mApp, $userId, $app, $request) { $lastSync = $request->get('from', null); $syncService = $app[‘syncService’]; $syncService->sync($lastSync, $userId); $response = new JsonResponse( $syncService->getResult() ); return $response; }
  • 34. Silex Implementation $app->get(“/apps/{mApp}/users/{userId}/changes”, function ($mApp, $userId, $app, $request) { $lastSync = $request->get('from', null); $syncService = $app[‘syncService’]; $syncService->sync($lastSync, $userId); $response = new JsonResponse( $syncService->getResult() ); return $response; }
  • 35. Silex Implementation $app->get(“/apps/{mApp}/users/{userId}/changes”, function ($mApp, $userId, $app, $request) { $lastSync = $request->get('from', null); $syncService = $app[‘syncService’]; $syncService->sync($lastSync, $userId); $response = new JsonResponse( $syncService->getResult() ); return $response; }
  • 36. Silex Implementation $app->get(“/apps/{mApp}/users/{userId}/merge”, function ($mApp, $userId, $app, $request) { $lastSync = $request->get('from', null); $data = $request->get(‘data’, false); $syncService = $app[‘syncService’]; $syncService->merge($data, $lastSync, $userId); $response = new JsonResponse( $syncService->getResult() ); return $response; }
  • 37. Silex Implementation $app->get(“/apps/{mApp}/users/{userId}/merge”, function ($mApp, $userId, $app, $request) { $lastSync = $request->get('from', null); $data = $request->get(‘data’, false); $syncService = $app[‘syncService’]; $syncService->merge($data, $lastSync, $userId); $response = new JsonResponse( $syncService->getResult() ); return $response; }
  • 38. Silex Implementation $app->get(“/apps/{mApp}/users/{userId}/merge”, function ($mApp, $userId, $app, $request) { $lastSync = $request->get('from', null); $data = $request->get(‘data’, false); $syncService = $app[‘syncService’]; $syncService->merge($data, $lastSync, $userId); $response = new JsonResponse( $syncService->getResult() ); return $response; }
  • 39. Silex Implementation $app->get(“/apps/{mApp}/users/{userId}/merge”, function ($mApp, $userId, $app, $request) { $lastSync = $request->get('from', null); $data = $request->get(‘data’, false); $syncService = $app[‘syncService’]; $syncService->merge($data, $lastSync, $userId); $response = new JsonResponse( $syncService->getResult() ); return $response; }
  • 40. Silex Implementation $app->get(“/apps/{mApp}/users/{userId}/merge”, function ($mApp, $userId, $app, $request) { $lastSync = $request->get('from', null); $data = $request->get(‘data’, false); $syncService = $app[‘syncService’]; $syncService->merge($data, $lastSync, $userId); $response = new JsonResponse( $syncService->getResult() ); return $response; }
  • 41. Silex Implementation $app['mongodb'] = new MongoDb(…); $app[‘changesRepo’] = new ChangesRepository( $app[‘mongodb’] ); $app[‘syncService’] ? new SyncService( $app[‘changesRepo’] );
  • 42. Get changes GET /apps/:app/users/:user_id/changes?from=:from timestamp?
  • 43. Server suggest the sync time timestamp are inaccurate server suggests the “from” parameter to be used in the next request
  • 44. Server suggest the sync time GET /changes { ‘next’ : 12345, ‘data’: […] } c1 server
  • 45. Server suggest the sync time GET /changes { ‘next’ : 12345, ‘data’: […] } c1 server GET /changes?from=12345 { ‘next’ : 45678, ‘data’: […] }
  • 46. 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
  • 47. what to transfer we choose to transfer states {id: ‘1’, ’type’: ‘measure’, ‘_deleted’: true} {id: 2’, ‘type’: ‘note’} {id: ‘3’, ‘type’: ‘note’} ps: soft delete all the things!
  • 48. unique identifiers How do we generate an unique id in a distributed system?
  • 49. unique identifiers How do we generate an unique id in a distributed system? UUID (RFC 4122): several implementations in PHP (https://github.com/ramsey/uuid)
  • 50. unique identifiers How do we generate an unique id in a distributed system? Local/Global Id: only the server generates GUIDs clients use local ids to manage their records
  • 51. unique identifiers POST /merge { ‘data’: [ {’lid’: ‘1’, …}, {‘lid’: ‘2’, …} ] } c1 server { ‘data’: [ {‘guid’: ‘58f0bdd7-1400’, ’lid’: ‘1’, …}, {‘guid’: ‘6f9f3ec9-1400’, ‘lid’: ‘2’, …} ] }
  • 52. conflict resolution algorithm (plain data) mobile generated data are “temporary” until sync to server server handles conflicts resolution
  • 53. conflict resolution algorithm (plain data) conflict resolution: domain indipendent: e.g. last-write wins domain dipendent: use domain knowledge to resolve
  • 54. 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)
  • 55. 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)
  • 56. 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) no conflict
  • 57. 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) remote wins
  • 58. 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) server wins
  • 59. 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
  • 60. 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
  • 61. 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
  • 62. 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
  • 63. 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
  • 64. 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’ }}
  • 65. conflict resolution algorithm (hierarchical data) How to manage hierarchical data? { ‘lid’ : ‘123456’, ‘type’ : ‘baby’, … } { ‘lid’ : ‘123456’, ‘type’ : ‘temperature’, ‘baby_id : ‘123456’ }
  • 66. 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’ }
  • 67. 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; } …
  • 68. 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; } … parent records first
  • 69. 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; } …
  • 70. 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
  • 71. … if ($newRootRecord->updated > $s->updated) { update($s, $newRecord); updateRecordIds($newRootRecord, $data); send($newRootRecord); continue; } else { updateRecordIds($s, $data); updateRemote($newRecord, $s); } } else { sync($data); } } conflict resolution algorithm (hierarchical data) remote wins
  • 72. … if ($newRootRecord->updated > $s->updated) { update($s, $newRecord); updateRecordIds($newRootRecord, $data); send($newRootRecord); continue; } else { updateRecordIds($s, $data); updateRemote($newRecord, $s); } } else { sync($data); } } conflict resolution algorithm (hierarchical data) server wins
  • 73. conflict resolution algorithm (hierarchical data) { ‘lid’: ‘1’, ‘data’ : ‘AAA’ ‘updated’: ’100’ } { ‘lid’: ‘2’, ‘parent’: ‘1’, ‘data’ : ‘hello!’, ‘updated’: ’15’ } POST /merge c1 server
  • 74. 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’ }
  • 75. 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’ }
  • 76. 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’ }}
  • 77. enforcing domain constraints e.g. “only one temperature can be registered in a given day” how to we enforce domain constraints on data?
  • 78. 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
  • 79. 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
  • 80. enforcing domain constraints from findByGuid to findSimilar first lookup by GUID then by domain rules “two measures are similar if are referred to the same date”
  • 82. enforcing domain constraints { ’guid’: ‘af54d’, ‘when’: ‘20141005’ } c1 server
  • 83. enforcing domain constraints { ‘lid’: ‘1’, ‘when’: ‘20141005’ } { ’guid’: ‘af54d’, ‘when’: ‘20141005’ } c1 server
  • 84. enforcing domain constraints { ‘lid’: ‘1’, ‘when’: ‘20141005’ } { ’guid’: ‘af54d’, ‘when’: ‘20141005’ } POST /merge c1 server
  • 85. enforcing domain constraints { ‘lid’: ‘1’, ‘when’: ‘20141005’ } { ’guid’: ‘af54d’, ‘when’: ‘20141005’ } POST /merge c1 server
  • 86. enforcing domain constraints { ‘lid’: ‘1’, ‘when’: ‘20141005’ } { ’guid’: ‘af54d’, ‘when’: ‘20141005’ } POST /merge c1 server { ’guid’: ‘af54d’, ‘when’: ‘20141005’ }
  • 87. dealing with binary data Binary data uploaded via custom endpoint Sync data remains small Uploads can be resumed
  • 88. dealing with binary data Two steps* 1) data are synchronized 2) related images are uploaded * this means record without file for a given time
  • 89. 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
  • 90. What we learned Implementing this stuff is tricky Explore existing solution if you can Understanding the domain is important
  • 93. 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
  • 94. Couchbase Mobile Gateways handles sync Data flows through channels - partition data set - authorization - limit the data Use revision trees
  • 95. Riak Distributed DB Eventually/Strong Consistency Data Types Configurable conflict resolution - db level for built-in data types - application level for custom data
  • 96. That’s all folks! Questions? Please leave feedback! https://joind.in/12959
  • 97. http://www.objc.io/issue-10/sync-case-study.html http://www.objc.io/issue-10/data-synchronization.html https://dev.evernote.com/media/pdf/edam-sync.pdf http://blog.helftone.com/clear-in-the-icloud/ http://strongloop.com/strongblog/node-js-replication-mobile-offline-sync-loopback/ http://blog.denivip.ru/index.php/2014/04/data-syncing-in-core-data-based-ios-apps/?lang=en http://inessential.com/2014/02/15/vesper_sync_diary_8_the_problem_of_un http://culturedcode.com/things/blog/2010/12/state-of-sync-part-1.html http://programmers.stackexchange.com/questions/206310/data-synchronization-in-mobile-apps-multiple- devices-multiple-users http://bricklin.com/offline.htm http://blog.couchbase.com/why-mobile-sync Links
  • 98. 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/ http://blog.8thlight.com/rylan-dirksen/2013/10/04/synchronization-in-a-distributed-system.html 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
  • 99. 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