SlideShare a Scribd company logo
Building a maintainable 
bi-directional cross 
platform protocol 
Pavel Dovbush 
William Lewis 
@
Background 
Solution and Implementation 
Examples
● Application Programming Interface 
● Operations 
● Inputs 
● Outputs 
● Type definitions 
● Independent of implementation 
API 
API
Building a maintainable bi-directional cross platform protocol
Requirements 
Perfect Client Server API: 
● Just works – Magic! :) 
● Flexible 
● Extensible 
● Testable 
● Maintainable 
● Platform and language neutral 
● Focused on features, not bytes over the wire 
Requirements
Overview 
● Encoding 
● Message exchange 
● Data access 
data 
access 
Server 
Client 
exchange data 
exchange access 
serialise 
deserialise 
Overview
REST+JSON 
PHP 
array 
Server 
Client 
URI JS 
Ajax Object 
JSON 
URL 
REST + JSON
REST+JSON problems 
Message exchange: 
● Client: HTTP request/response model 
● Server: URI-based, config on web- or app- server 
Data access: 
● No canonical definition 
● No versioning 
● Duplicate implementations and configuration 
REST + JSON 
Encoding: 
● Server: JSON 
● Client: URLEncode
Badoo APIs 
Badoo APIs 
Core API 
Mobile 
API 
???
Background 
Solution and Implementation 
Examples
Protocol implementations 
SOAP 
Protocol Values
Building a maintainable bi-directional cross platform protocol
Protocol values 
● Protocol description 
● Encoding 
● Data access 
● Message exchange 
● Versioning 
Protocol
Protobuf + Own RPC 
Generated 
class 
Server 
Client 
Events Generated 
Events class 
Protobuf 
Protobuf 
Description, versioning 
Usage
Google Protocol Buffers 
● Interface description language 
● Internal representation 
● Language support 
○ v2.3 plugin support 
● Encoding and network efficiency 
Protcol values
Interface description language 
Protobuf is self-describing - descriptor.proto 
Interface description language 
● enum 
● message 
● field 
● service 
● option
Interface description language 
Label Type Name Number 
optional 
required 
repeated 
bool 
string 
message 
enum 
float 
int32 
+ more numeric 
field_name = 1; 
required string user_name = 1; 
optional uint32 age = 2; 
Interface description language
Interface description language 
enum Role { 
ADMIN = 1; 
USER = 2; 
} 
message User { 
required string name = 1; 
repeated string nickname = 2; 
optional uint32 age = 3; 
required Role role = 4; 
} 
Interface description language
Protobuf usage 
Encoding: 
● Only binary 
Message exchange: 
● Simple RPC 
Data access: 
● No support for PHP 
● No support for JS 
Protobuf compiler plugins
Protobuf v2.3.0 compiler plugins 
● Brilliant internal architecture 
● Very simple plugin system 
● Can generate any code in any language 
● IDL is completely separated from serialization part 
● gist with example 
Protobuf complier plugins
Encoding 
Encoding 
Core API 
Mobile 
Native binary API 
serialization 
Custom JSON 
serialization
Performance 
Performance
Code auto-generation 
● WebSite DEVEL - On any request if ‘.proto’ file is 
newer than generated code - regenerate 
● Mobile DEVEL - Grunt task - regenerate on file 
change 
● PRODUCTION - generate before deploy 
Code auto-generation
Message exchange 
service SearchService { 
rpc Search (SearchRequest) 
returns (SearchResponse); 
} 
● Too simple for a complex application 
● We need a wrapper for every Request/Response 
● Anytime responses 
Message exchange
Message exchange (two-way RPC) 
new RPC(request_type, parameter) 
.on(response_type, callback) 
.on([type1, type2], callback) 
.request(); 
RPC.any.on(type3, callback); 
function callback(err, /** Type1 */ response1) {} 
request_type & response_type are values of enum 
MessageType 
parameter & response are Protobuf messages 
Message exchange
Versioning 
Old clients ignore: 
● new fields 
● unsupported commands 
Migrating to new protocol version: 
● cause compilation error on field removal 
Versioning
Take aways 
● Protocol defined in one place 
● Code uses data-access classes 
● Validation 
● Encoding can vary 
● Flexible message exchange 
● Versioning 
● Any part can be changed without affecting anything 
else 
Summary
Background 
Solution and Implementation 
Examples
Building a service 
Example
Example
Building a service 
● Location search 
○ Client query: city name 
○ Server response: list of cities 
(ID, name, lat, long) 
● Client notification 
○ Anytime server response: user message 
Example
Protobuf definition 
enum MessageType { 
// body: CityQuery 
SERVER_SEARCH_CITIES = 1; 
// body: Cities 
CLIENT_FOUND_CITIES = 2; 
// body : ClientNotification 
CLIENT_NOTIFICATION = 3; 
} 
message ClientNotification { 
required string id = 1; 
optional string title = 2; 
optional string message = 3; 
} 
message CityQuery { 
optional string name = 1; 
} 
message Cities { 
repeated City cities = 1; 
} 
message City { 
required int32 id = 1; 
required string name = 2; 
optional double longitude = 3; 
optional double latitude = 4; 
} 
Example protobuf
Protobuf definition 
message RPCMessage { 
required int32 version = 1; 
optional int32 message_id = 2; 
repeated MessageBody body = 3; 
} 
message MessageBody { 
required MessageType message_type = 1; 
optional CityQuery city_query = 2; 
optional Cities cities = 3; 
optional ClientNotification client_notification = 4; 
} 
Example protobuf
Generated classes examples 
define(['GPB/gpb2'], function(/** $gpb */$gpb) { 
var Protocol = $gpb.namespace('Demo'); 
/** 
* CityQuery 
* @class {Protocol.CityQuery} 
* @extends {$gpb.Message} 
*/ 
var CityQuery = Protocol.CityQuery = function() { 
$gpb.Message.apply(this, arguments); 
}; 
$gpb.extend(CityQuery, CityQuery, $gpb.$gpb.Message); 
Message); 
CityQuery.prototype.$gpb = 'Demo.CityQuery'; 
CityQuery.prototype._prototype._descriptor descriptor = {"= fields": {"fields": {"name": {"name": {"type": {"type": 9, "number": 9, "number": 
1, 
1, "label": 1}}}; 
"label": 1}}}; 
return CityQuery; 
}); 
Generated class
Generated classes examples 
<?php 
namespace GPBJSDemo; 
class CityQuery GPBJSBaseMessage 
{ 
protected static $name = 'Demo.CityQuery'; 
extends GPBJSBaseMessage 
protected static $fields = array( 
'name' => array('type' => 'string', 'optional' => true, 'repeatable' => false, 
'hash' => false, 'raw' => False, 'is_enum' => false, 'is_message' => false), 
); 
static $fields = array( 
=> array('type' => 'string', 'optional' => true, 'repeatable' => false, 'hash' => 
false, 'raw' => False, 'is_enum' => false, 'is_message' => false), 
public function setName($value) 
{ 
$this->_setFieldValue('name', $value); 
return $this; 
} 
public function getName() 
{ 
return $this->_getFieldValue('name'); 
} 
} 
Generated class
RPC city query example 
new RPC(Protocol.MessageType.SERVER_SEARCH_CITIES, cityQuery) 
.on(Protocol.MessageType.CLIENT_CITIES, onCities) 
.on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification) 
.request(); 
function onCities (err, /** Protocol.Cities */ cities) { 
if (err) { /* error handling */ return; } 
for (var city in cities.getCities()) { 
cityListView.update(city.getId(), city.getName()); 
} 
} 
function onNotification ( err, /** Protocol.ClientNotification */ notification) { 
alert(notification.getTitle() + ‘n’ + notification.getMessage()); 
} 
Example usage
RPC city query example 
var cityQuery = new Protocol.CityQuery().setName(‘london’); 
new RPC(Protocol.MessageType.SERVER_SEARCH_CITIES, cityQuery) 
.on(Protocol.MessageType.CLIENT_CITIES, onCities) 
.on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification) 
.request(); 
function onCities (err, /** Protocol.Cities */ cities) { 
if (err) { /* error handling */ return; } 
for (var city in cities.getCities()) { 
cityListView.update(city.getId(), city.getName()); 
} 
} 
function onNotification ( err, /** Protocol.ClientNotification */ notification) { 
alert(notification.getTitle() + ‘n’ + notification.getMessage()); 
} 
Example usage
RPC city query example 
var cityQuery = new Protocol.CityQuery().setName(‘london’); 
new RPC(Protocol.MessageType.SERVER_SEARCH_CITIES, cityQuery) 
.on(Protocol.MessageType.CLIENT_CITIES, onCities) 
.on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification) 
.request(); 
function onCities (err, /** Protocol.Cities */ cities) { 
if (err) { /* error handling */ return; } 
for (var city in cities.getCities()) { 
cityListView.update(city.getId(), city.getName()); 
} 
} 
function onNotification ( err, /** Protocol.ClientNotification */ notification) { 
alert(notification.getTitle() + ‘n’ + notification.getMessage()); 
} 
Example usage
RPC city query example 
var cityQuery = new Protocol.CityQuery().setName(‘london’); 
new RPC(Protocol.MessageType.SERVER_SEARCH_CITIES, cityQuery) 
.on(Protocol.MessageType.CLIENT_CITIES, onCities) 
.on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification) 
.request(); 
function onCities (err, /** Protocol.Cities */ cities) { 
if (err) { /* error handling */ return; } 
for (var city in cities.getCities()) { 
cityListView.update(city.getId(), city.getName()); 
} 
} 
function onNotification ( err, /** Protocol.ClientNotification */ notification) { 
alert(notification.getTitle() + ‘n’ + notification.getMessage()); 
} 
Example usage
RPC city query example 
var cityQuery = new Protocol.CityQuery().setName(‘london’); 
new RPC(Protocol.MessageType.SERVER_SEARCH_CITIES, cityQuery) 
.on(Protocol.MessageType.CLIENT_CITIES, onCities) 
.on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification) 
.request(); 
function onCities (err, /** Protocol.Cities */ cities) { 
if (err) { /* error handling */ return; } 
for (var city in cities.getCities()) { 
cityListView.update(city.getId(), city.getName()); 
} 
} 
function onNotification ( err, /** Protocol.ClientNotification */ notification) { 
alert(notification.getTitle() + ‘n’ + notification.getMessage()); 
} 
Example usage
RPC city query example 
var cityQuery = new Protocol.CityQuery().setName(‘london’); 
new RPC(Protocol.MessageType.SERVER_SEARCH_CITIES, cityQuery) 
.on(Protocol.MessageType.CLIENT_CITIES, onCities) 
.on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification) 
.request(); 
function onCities (err, /** Protocol.Cities */ cities) { 
if (err) { /* error handling */ return; } 
for (var city in cities.getCities()) { 
cityListView.update(city.getId(), city.getName()); 
} 
} 
function onNotification ( err, /** Protocol.ClientNotification */ notification) { 
alert(notification.getTitle() + ‘n’ + notification.getMessage()); 
} 
Example usage
RPC city query example 
var cityQuery = new Protocol.CityQuery().setName(‘london’); 
new RPC(Protocol.MessageType.SERVER_SEARCH_CITIES, cityQuery) 
.on(Protocol.MessageType.CLIENT_CITIES, onCities) 
.on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification) 
.request(); 
function onCities (err, /** Protocol.Cities */ cities) { 
if (err) { /* error handling */ return; } 
for (var city in cities.getCities()) { 
cityListView.update(city.getId(), city.getName()); 
} 
} 
function onNotification ( err, /** Protocol.ClientNotification */ notification) { 
alert(notification.getTitle() + ‘n’ + notification.getMessage()); 
} 
Example usage
RPC anytime response example 
RPC.any.on(Protocol.MessageType.CLIENT_NOTIFICATION, 
onNotification); 
function onNotification ( err, /** Protocol.ClientNotification */ notification) { 
alert(notification.getTitle() + ‘n’ + notification.getMessage()); 
} 
Example usage
Building a maintainable bi-directional cross 
platform protocol 
● REST + JSON 
● Protocol values 
○ Interface description language 
○ Encoding and performance 
○ Protobuf compiler plugins 
○ Code auto-generation 
○ Message exchange (two-way RPC) 
○ Versioning 
● Examples 
Summary
Thanks! Questions? 
Pavel Dovbush <dpp@corp.badoo.com> 
William Lewis <william.lewis@corp.badoo.com> 
@netproteus 
Slides: techblog.badoo.com 
Thanks: 
Google team for Protobuf itself 
Andrey Nigmatulin <anight@corp.badoo.com> for bringing GPB in Badoo in 2009

More Related Content

PPT
Managed Compiler
PPTX
PPTX
Применение паттерна Page Object для автоматизации веб сервисов
PDF
GOCON Autumn (Story of our own Monitoring Agent in golang)
PPTX
Применение паттерна Page Object для автоматизации веб сервисов - новый взгляд
PDF
linq with Exampls
PDF
Разработка кросс-платформенного кода между iPhone &lt; -> Windows с помощью o...
Managed Compiler
Применение паттерна Page Object для автоматизации веб сервисов
GOCON Autumn (Story of our own Monitoring Agent in golang)
Применение паттерна Page Object для автоматизации веб сервисов - новый взгляд
linq with Exampls
Разработка кросс-платформенного кода между iPhone &lt; -> Windows с помощью o...

What's hot (18)

PPTX
What I learned about APIs in my first year at Google
PDF
JSON-RPC Proxy Generation with PHP 5
PDF
Lecture 3 getting_started_with__c_
PDF
Multi-language FBP with flowex
PDF
.Net passé, présent et futur
PDF
XML-RPC (XML Remote Procedure Call)
PDF
Engineering Efficiency in LINE
PDF
Anton Mishchuk - Multi-language FBP with Flowex
PDF
Go 1.10 Release Party - PDX Go
PDF
Php And Web Services
PPTX
Function overloading and overriding
PPT
Debugging Applications with GNU Debugger
PDF
Flowex - Railway Flow-Based Programming with Elixir GenStage.
PPT
3 Function Overloading
PDF
Hyperledger 구조 분석
PPT
Socket programming
PPT
Easy Steps to implement UDP Server and Client Sockets
PDF
Microservices dengan Go-Kit
What I learned about APIs in my first year at Google
JSON-RPC Proxy Generation with PHP 5
Lecture 3 getting_started_with__c_
Multi-language FBP with flowex
.Net passé, présent et futur
XML-RPC (XML Remote Procedure Call)
Engineering Efficiency in LINE
Anton Mishchuk - Multi-language FBP with Flowex
Go 1.10 Release Party - PDX Go
Php And Web Services
Function overloading and overriding
Debugging Applications with GNU Debugger
Flowex - Railway Flow-Based Programming with Elixir GenStage.
3 Function Overloading
Hyperledger 구조 분석
Socket programming
Easy Steps to implement UDP Server and Client Sockets
Microservices dengan Go-Kit
Ad

Similar to Building a maintainable bi-directional cross platform protocol (20)

PPTX
Building your First gRPC Service
PDF
Rest style web services (google protocol buffers) prasad nirantar
PDF
Teach your (micro)services talk Protocol Buffers with gRPC.
PPT
JavaOne 2009 - TS-5276 - RESTful Protocol Buffers
PPTX
Golang proto buff_ixxo
PDF
Creating Great REST and gRPC API Experiences (in Swift)
PPTX
CocoaConf: The Language of Mobile Software is APIs
PDF
Build Great Networked APIs with Swift, OpenAPI, and gRPC
PDF
Next Generation Client APIs in Envoy Mobile
PDF
Cloud Native API Design and Management
PDF
Fast and Reliable Swift APIs with gRPC
PPTX
Rockin' Protobuf in Ruby
PPTX
Introduction to gRPC. Advantages and Disadvantages
PPTX
The Right Kind of API – How To Choose Appropriate API Protocols and Data Form...
PPTX
Thrift vs Protocol Buffers vs Avro - Biased Comparison
PDF
Generating Unified APIs with Protocol Buffers and gRPC
PDF
Usable APIs at Scale
PPTX
REST in Peace. Long live gRPC! @ Codineers
PPTX
Google Protocol Buffers + gRPC
PDF
REST in Peace. Long live gRPC!
Building your First gRPC Service
Rest style web services (google protocol buffers) prasad nirantar
Teach your (micro)services talk Protocol Buffers with gRPC.
JavaOne 2009 - TS-5276 - RESTful Protocol Buffers
Golang proto buff_ixxo
Creating Great REST and gRPC API Experiences (in Swift)
CocoaConf: The Language of Mobile Software is APIs
Build Great Networked APIs with Swift, OpenAPI, and gRPC
Next Generation Client APIs in Envoy Mobile
Cloud Native API Design and Management
Fast and Reliable Swift APIs with gRPC
Rockin' Protobuf in Ruby
Introduction to gRPC. Advantages and Disadvantages
The Right Kind of API – How To Choose Appropriate API Protocols and Data Form...
Thrift vs Protocol Buffers vs Avro - Biased Comparison
Generating Unified APIs with Protocol Buffers and gRPC
Usable APIs at Scale
REST in Peace. Long live gRPC! @ Codineers
Google Protocol Buffers + gRPC
REST in Peace. Long live gRPC!
Ad

Recently uploaded (20)

PDF
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
PPTX
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
PPTX
bas. eng. economics group 4 presentation 1.pptx
PDF
R24 SURVEYING LAB MANUAL for civil enggi
PPTX
FINAL REVIEW FOR COPD DIANOSIS FOR PULMONARY DISEASE.pptx
PDF
PPT on Performance Review to get promotions
PPTX
CARTOGRAPHY AND GEOINFORMATION VISUALIZATION chapter1 NPTE (2).pptx
PPTX
Sustainable Sites - Green Building Construction
PDF
Model Code of Practice - Construction Work - 21102022 .pdf
PPTX
CH1 Production IntroductoryConcepts.pptx
PPTX
UNIT 4 Total Quality Management .pptx
PDF
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
PDF
PRIZ Academy - 9 Windows Thinking Where to Invest Today to Win Tomorrow.pdf
PPTX
IOT PPTs Week 10 Lecture Material.pptx of NPTEL Smart Cities contd
PPTX
Welding lecture in detail for understanding
PPTX
additive manufacturing of ss316l using mig welding
PDF
Embodied AI: Ushering in the Next Era of Intelligent Systems
PPTX
OOP with Java - Java Introduction (Basics)
PPTX
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
PPTX
UNIT-1 - COAL BASED THERMAL POWER PLANTS
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
bas. eng. economics group 4 presentation 1.pptx
R24 SURVEYING LAB MANUAL for civil enggi
FINAL REVIEW FOR COPD DIANOSIS FOR PULMONARY DISEASE.pptx
PPT on Performance Review to get promotions
CARTOGRAPHY AND GEOINFORMATION VISUALIZATION chapter1 NPTE (2).pptx
Sustainable Sites - Green Building Construction
Model Code of Practice - Construction Work - 21102022 .pdf
CH1 Production IntroductoryConcepts.pptx
UNIT 4 Total Quality Management .pptx
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
PRIZ Academy - 9 Windows Thinking Where to Invest Today to Win Tomorrow.pdf
IOT PPTs Week 10 Lecture Material.pptx of NPTEL Smart Cities contd
Welding lecture in detail for understanding
additive manufacturing of ss316l using mig welding
Embodied AI: Ushering in the Next Era of Intelligent Systems
OOP with Java - Java Introduction (Basics)
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
UNIT-1 - COAL BASED THERMAL POWER PLANTS

Building a maintainable bi-directional cross platform protocol

  • 1. Building a maintainable bi-directional cross platform protocol Pavel Dovbush William Lewis @
  • 2. Background Solution and Implementation Examples
  • 3. ● Application Programming Interface ● Operations ● Inputs ● Outputs ● Type definitions ● Independent of implementation API API
  • 5. Requirements Perfect Client Server API: ● Just works – Magic! :) ● Flexible ● Extensible ● Testable ● Maintainable ● Platform and language neutral ● Focused on features, not bytes over the wire Requirements
  • 6. Overview ● Encoding ● Message exchange ● Data access data access Server Client exchange data exchange access serialise deserialise Overview
  • 7. REST+JSON PHP array Server Client URI JS Ajax Object JSON URL REST + JSON
  • 8. REST+JSON problems Message exchange: ● Client: HTTP request/response model ● Server: URI-based, config on web- or app- server Data access: ● No canonical definition ● No versioning ● Duplicate implementations and configuration REST + JSON Encoding: ● Server: JSON ● Client: URLEncode
  • 9. Badoo APIs Badoo APIs Core API Mobile API ???
  • 10. Background Solution and Implementation Examples
  • 11. Protocol implementations SOAP Protocol Values
  • 13. Protocol values ● Protocol description ● Encoding ● Data access ● Message exchange ● Versioning Protocol
  • 14. Protobuf + Own RPC Generated class Server Client Events Generated Events class Protobuf Protobuf Description, versioning Usage
  • 15. Google Protocol Buffers ● Interface description language ● Internal representation ● Language support ○ v2.3 plugin support ● Encoding and network efficiency Protcol values
  • 16. Interface description language Protobuf is self-describing - descriptor.proto Interface description language ● enum ● message ● field ● service ● option
  • 17. Interface description language Label Type Name Number optional required repeated bool string message enum float int32 + more numeric field_name = 1; required string user_name = 1; optional uint32 age = 2; Interface description language
  • 18. Interface description language enum Role { ADMIN = 1; USER = 2; } message User { required string name = 1; repeated string nickname = 2; optional uint32 age = 3; required Role role = 4; } Interface description language
  • 19. Protobuf usage Encoding: ● Only binary Message exchange: ● Simple RPC Data access: ● No support for PHP ● No support for JS Protobuf compiler plugins
  • 20. Protobuf v2.3.0 compiler plugins ● Brilliant internal architecture ● Very simple plugin system ● Can generate any code in any language ● IDL is completely separated from serialization part ● gist with example Protobuf complier plugins
  • 21. Encoding Encoding Core API Mobile Native binary API serialization Custom JSON serialization
  • 23. Code auto-generation ● WebSite DEVEL - On any request if ‘.proto’ file is newer than generated code - regenerate ● Mobile DEVEL - Grunt task - regenerate on file change ● PRODUCTION - generate before deploy Code auto-generation
  • 24. Message exchange service SearchService { rpc Search (SearchRequest) returns (SearchResponse); } ● Too simple for a complex application ● We need a wrapper for every Request/Response ● Anytime responses Message exchange
  • 25. Message exchange (two-way RPC) new RPC(request_type, parameter) .on(response_type, callback) .on([type1, type2], callback) .request(); RPC.any.on(type3, callback); function callback(err, /** Type1 */ response1) {} request_type & response_type are values of enum MessageType parameter & response are Protobuf messages Message exchange
  • 26. Versioning Old clients ignore: ● new fields ● unsupported commands Migrating to new protocol version: ● cause compilation error on field removal Versioning
  • 27. Take aways ● Protocol defined in one place ● Code uses data-access classes ● Validation ● Encoding can vary ● Flexible message exchange ● Versioning ● Any part can be changed without affecting anything else Summary
  • 28. Background Solution and Implementation Examples
  • 31. Building a service ● Location search ○ Client query: city name ○ Server response: list of cities (ID, name, lat, long) ● Client notification ○ Anytime server response: user message Example
  • 32. Protobuf definition enum MessageType { // body: CityQuery SERVER_SEARCH_CITIES = 1; // body: Cities CLIENT_FOUND_CITIES = 2; // body : ClientNotification CLIENT_NOTIFICATION = 3; } message ClientNotification { required string id = 1; optional string title = 2; optional string message = 3; } message CityQuery { optional string name = 1; } message Cities { repeated City cities = 1; } message City { required int32 id = 1; required string name = 2; optional double longitude = 3; optional double latitude = 4; } Example protobuf
  • 33. Protobuf definition message RPCMessage { required int32 version = 1; optional int32 message_id = 2; repeated MessageBody body = 3; } message MessageBody { required MessageType message_type = 1; optional CityQuery city_query = 2; optional Cities cities = 3; optional ClientNotification client_notification = 4; } Example protobuf
  • 34. Generated classes examples define(['GPB/gpb2'], function(/** $gpb */$gpb) { var Protocol = $gpb.namespace('Demo'); /** * CityQuery * @class {Protocol.CityQuery} * @extends {$gpb.Message} */ var CityQuery = Protocol.CityQuery = function() { $gpb.Message.apply(this, arguments); }; $gpb.extend(CityQuery, CityQuery, $gpb.$gpb.Message); Message); CityQuery.prototype.$gpb = 'Demo.CityQuery'; CityQuery.prototype._prototype._descriptor descriptor = {"= fields": {"fields": {"name": {"name": {"type": {"type": 9, "number": 9, "number": 1, 1, "label": 1}}}; "label": 1}}}; return CityQuery; }); Generated class
  • 35. Generated classes examples <?php namespace GPBJSDemo; class CityQuery GPBJSBaseMessage { protected static $name = 'Demo.CityQuery'; extends GPBJSBaseMessage protected static $fields = array( 'name' => array('type' => 'string', 'optional' => true, 'repeatable' => false, 'hash' => false, 'raw' => False, 'is_enum' => false, 'is_message' => false), ); static $fields = array( => array('type' => 'string', 'optional' => true, 'repeatable' => false, 'hash' => false, 'raw' => False, 'is_enum' => false, 'is_message' => false), public function setName($value) { $this->_setFieldValue('name', $value); return $this; } public function getName() { return $this->_getFieldValue('name'); } } Generated class
  • 36. RPC city query example new RPC(Protocol.MessageType.SERVER_SEARCH_CITIES, cityQuery) .on(Protocol.MessageType.CLIENT_CITIES, onCities) .on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification) .request(); function onCities (err, /** Protocol.Cities */ cities) { if (err) { /* error handling */ return; } for (var city in cities.getCities()) { cityListView.update(city.getId(), city.getName()); } } function onNotification ( err, /** Protocol.ClientNotification */ notification) { alert(notification.getTitle() + ‘n’ + notification.getMessage()); } Example usage
  • 37. RPC city query example var cityQuery = new Protocol.CityQuery().setName(‘london’); new RPC(Protocol.MessageType.SERVER_SEARCH_CITIES, cityQuery) .on(Protocol.MessageType.CLIENT_CITIES, onCities) .on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification) .request(); function onCities (err, /** Protocol.Cities */ cities) { if (err) { /* error handling */ return; } for (var city in cities.getCities()) { cityListView.update(city.getId(), city.getName()); } } function onNotification ( err, /** Protocol.ClientNotification */ notification) { alert(notification.getTitle() + ‘n’ + notification.getMessage()); } Example usage
  • 38. RPC city query example var cityQuery = new Protocol.CityQuery().setName(‘london’); new RPC(Protocol.MessageType.SERVER_SEARCH_CITIES, cityQuery) .on(Protocol.MessageType.CLIENT_CITIES, onCities) .on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification) .request(); function onCities (err, /** Protocol.Cities */ cities) { if (err) { /* error handling */ return; } for (var city in cities.getCities()) { cityListView.update(city.getId(), city.getName()); } } function onNotification ( err, /** Protocol.ClientNotification */ notification) { alert(notification.getTitle() + ‘n’ + notification.getMessage()); } Example usage
  • 39. RPC city query example var cityQuery = new Protocol.CityQuery().setName(‘london’); new RPC(Protocol.MessageType.SERVER_SEARCH_CITIES, cityQuery) .on(Protocol.MessageType.CLIENT_CITIES, onCities) .on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification) .request(); function onCities (err, /** Protocol.Cities */ cities) { if (err) { /* error handling */ return; } for (var city in cities.getCities()) { cityListView.update(city.getId(), city.getName()); } } function onNotification ( err, /** Protocol.ClientNotification */ notification) { alert(notification.getTitle() + ‘n’ + notification.getMessage()); } Example usage
  • 40. RPC city query example var cityQuery = new Protocol.CityQuery().setName(‘london’); new RPC(Protocol.MessageType.SERVER_SEARCH_CITIES, cityQuery) .on(Protocol.MessageType.CLIENT_CITIES, onCities) .on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification) .request(); function onCities (err, /** Protocol.Cities */ cities) { if (err) { /* error handling */ return; } for (var city in cities.getCities()) { cityListView.update(city.getId(), city.getName()); } } function onNotification ( err, /** Protocol.ClientNotification */ notification) { alert(notification.getTitle() + ‘n’ + notification.getMessage()); } Example usage
  • 41. RPC city query example var cityQuery = new Protocol.CityQuery().setName(‘london’); new RPC(Protocol.MessageType.SERVER_SEARCH_CITIES, cityQuery) .on(Protocol.MessageType.CLIENT_CITIES, onCities) .on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification) .request(); function onCities (err, /** Protocol.Cities */ cities) { if (err) { /* error handling */ return; } for (var city in cities.getCities()) { cityListView.update(city.getId(), city.getName()); } } function onNotification ( err, /** Protocol.ClientNotification */ notification) { alert(notification.getTitle() + ‘n’ + notification.getMessage()); } Example usage
  • 42. RPC city query example var cityQuery = new Protocol.CityQuery().setName(‘london’); new RPC(Protocol.MessageType.SERVER_SEARCH_CITIES, cityQuery) .on(Protocol.MessageType.CLIENT_CITIES, onCities) .on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification) .request(); function onCities (err, /** Protocol.Cities */ cities) { if (err) { /* error handling */ return; } for (var city in cities.getCities()) { cityListView.update(city.getId(), city.getName()); } } function onNotification ( err, /** Protocol.ClientNotification */ notification) { alert(notification.getTitle() + ‘n’ + notification.getMessage()); } Example usage
  • 43. RPC anytime response example RPC.any.on(Protocol.MessageType.CLIENT_NOTIFICATION, onNotification); function onNotification ( err, /** Protocol.ClientNotification */ notification) { alert(notification.getTitle() + ‘n’ + notification.getMessage()); } Example usage
  • 44. Building a maintainable bi-directional cross platform protocol ● REST + JSON ● Protocol values ○ Interface description language ○ Encoding and performance ○ Protobuf compiler plugins ○ Code auto-generation ○ Message exchange (two-way RPC) ○ Versioning ● Examples Summary
  • 45. Thanks! Questions? Pavel Dovbush <dpp@corp.badoo.com> William Lewis <william.lewis@corp.badoo.com> @netproteus Slides: techblog.badoo.com Thanks: Google team for Protobuf itself Andrey Nigmatulin <anight@corp.badoo.com> for bringing GPB in Badoo in 2009