Commit 565760ce authored by Giorgio Azzinnaro's avatar Giorgio Azzinnaro

testing packing and unpacking (python client)

`Db` gRPC service was improved to allow more flexibility,
`google.protobuf.Any` is used for packing/unpacking
parent 4bb73473
......@@ -7,24 +7,31 @@ option csharp_namespace = "ProdisDB.Protobuf";
option java_package = "com.prodisdb.protobuf";
option objc_class_prefix = "PDB";
message Empty {}
import "google/protobuf/any.proto";
message Serializable {
string type = 1;
bytes blob = 2;
service Db {
rpc Get (GetReq) returns (GetResp);
rpc Put (PutReq) returns (PutResp);
rpc Delete (DelReq) returns (DelResp);
}
message PrimaryKey {
string type = 1;
bytes uid = 2;
message GetReq {
}
service Db {
rpc Get (PrimaryKey) returns (Serializable);
message GetResp {
}
rpc Create (Serializable) returns (Empty);
message PutReq {
google.protobuf.Any serializable = 1;
}
message PutResp {
}
rpc Delete (PrimaryKey) returns (Empty);
message DelReq {
}
rpc Update (Serializable) returns (Empty);
message DelResp {
}
......@@ -18,34 +18,33 @@ prodisdb::server::Parser::Parser()
pool->FindFileByName("prodisdb/protobuf/options.proto");
pool->FindFileByName("test.proto");
}
prodisdb::server::Parser::~Parser()
{
}
void prodisdb::server::Parser::ParseMessage(const protobuf::Serializable& message)
void prodisdb::server::Parser::ParseMessage(const Any& serializable)
{
const Descriptor* definition = pool->FindMessageTypeByName(message.type());
std::string type = serializable.type_url();
const Descriptor* definition = pool->FindMessageTypeByName(type.substr(type.rfind('/')+1, string::npos));
const FieldDescriptor* fd;
// TODO Should check for multiple keys (might be supported later), for now throw error
for (int idx = 0; idx < definition->field_count(); idx++) {
fd = definition->field(idx);
std::cout
<< fd->full_name()
<< " is key: "
<< fd->options().GetExtension(prodisdb::protobuf::options).key()
<< std::endl;
if (fd->options().GetExtension(prodisdb::protobuf::options).key()) {
std::cout << fd->full_name() << " is key" << std::endl;
break;
}
}
std::cout << message.type() << std::endl;
Message* container = messageFactory.GetPrototype(definition)->New();
serializable.UnpackTo(container);
std::cout << container->GetReflection()->GetInt32(*container, fd) << std::endl;
}
prodisdb::server::Parser::ErrorCollector::ErrorCollector()
......
......@@ -5,6 +5,7 @@
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/dynamic_message.h>
#include <prodisdb/protobuf/db.pb.h>
#include <prodisdb/protobuf/options.pb.h>
......@@ -20,7 +21,7 @@ public:
Parser();
~Parser();
void ParseMessage(const protobuf::Serializable& message);
void ParseMessage(const Any& serializable);
private:
io::ZeroCopyInputStream* inputStream;
......@@ -29,6 +30,8 @@ private:
compiler::SourceTreeDescriptorDatabase* descriptorDb;
DescriptorPool* pool;
DynamicMessageFactory messageFactory;
class ErrorCollector : public compiler::MultiFileErrorCollector {
public:
ErrorCollector();
......
......@@ -30,19 +30,17 @@ void prodisdb::server::Server::HandleRpcs()
server->Wait();
}
grpc::Status prodisdb::server::Server::DbServiceImpl::Get(grpc::ServerContext* context, const prodisdb::protobuf::PrimaryKey* request, prodisdb::protobuf::Serializable* response)
grpc::Status prodisdb::server::Server::DbServiceImpl::Get(grpc::ServerContext* context, const prodisdb::protobuf::GetReq* request, prodisdb::protobuf::GetResp* response)
{
}
grpc::Status prodisdb::server::Server::DbServiceImpl::Create(grpc::ServerContext* context, const prodisdb::protobuf::Serializable* request, prodisdb::protobuf::Empty* response)
{
parser.ParseMessage(*request);
}
grpc::Status prodisdb::server::Server::DbServiceImpl::Delete(::grpc::ServerContext* context, const prodisdb::protobuf::PrimaryKey* request, prodisdb::protobuf::Empty* response)
grpc::Status prodisdb::server::Server::DbServiceImpl::Put(grpc::ServerContext* context, const prodisdb::protobuf::PutReq* request, prodisdb::protobuf::PutResp* response)
{
parser.ParseMessage(request->serializable());
return grpc::Status::OK;
}
grpc::Status prodisdb::server::Server::DbServiceImpl::Update(grpc::ServerContext* context, const prodisdb::protobuf::Serializable* request, prodisdb::protobuf::Empty* response)
grpc::Status prodisdb::server::Server::DbServiceImpl::Delete(grpc::ServerContext* context, const prodisdb::protobuf::DelReq* request, prodisdb::protobuf::DelResp* response)
{
}
......@@ -9,10 +9,6 @@
#include <prodisdb/protobuf/db.pb.h>
#include <prodisdb/protobuf/db.grpc.pb.h>
using prodisdb::protobuf::Empty;
using prodisdb::protobuf::Serializable;
using prodisdb::protobuf::PrimaryKey;
using prodisdb::protobuf::Db;
namespace prodisdb {
......@@ -33,14 +29,12 @@ private:
class DbServiceImpl : public Db::Service {
public:
grpc::Status Get(grpc::ServerContext* context, const prodisdb::protobuf::PrimaryKey* request, prodisdb::protobuf::Serializable* response) override;
grpc::Status Get(grpc::ServerContext* context, const prodisdb::protobuf::GetReq* request, prodisdb::protobuf::GetResp* response) override;
grpc::Status Create(grpc::ServerContext* context, const prodisdb::protobuf::Serializable* request, prodisdb::protobuf::Empty* response) override;
grpc::Status Put(grpc::ServerContext* context, const prodisdb::protobuf::PutReq* request, prodisdb::protobuf::PutResp* response) override;
grpc::Status Delete(::grpc::ServerContext* context, const prodisdb::protobuf::PrimaryKey* request, prodisdb::protobuf::Empty* response) override;
grpc::Status Delete(grpc::ServerContext* context, const prodisdb::protobuf::DelReq* request, prodisdb::protobuf::DelResp* response) override;
grpc::Status Update(grpc::ServerContext* context, const prodisdb::protobuf::Serializable* request, prodisdb::protobuf::Empty* response) override;
private:
Parser parser;
};
......
# Created by https://www.gitignore.io/api/python,virtualenv
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# dotenv
.env
# virtualenv
.venv
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
### VirtualEnv ###
# Virtualenv
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
[Bb]in
[Ii]nclude
[Ll]ib
[Ll]ib64
[Ll]ocal
[Ss]cripts
pyvenv.cfg
pip-selfcheck.json
# End of https://www.gitignore.io/api/python,virtualenv
syntax = "proto3";
package prodisdb.protobuf;
option go_package = "gitlab.com/prodisdb/protobuf/db";
option csharp_namespace = "ProdisDB.Protobuf";
option java_package = "com.prodisdb.protobuf";
option objc_class_prefix = "PDB";
import "google/protobuf/any.proto";
service Db {
rpc Get (GetReq) returns (GetResp);
rpc Put (PutReq) returns (PutResp);
rpc Delete (DelReq) returns (DelResp);
}
message GetReq {
}
message GetResp {
}
message PutReq {
google.protobuf.Any serializable = 1;
}
message PutResp {
}
message DelReq {
}
message DelResp {
}
This diff is collapsed.
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
import grpc
import prodisdb.protobuf.db_pb2 as prodisdb_dot_protobuf_dot_db__pb2
class DbStub(object):
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.Get = channel.unary_unary(
'/prodisdb.protobuf.Db/Get',
request_serializer=prodisdb_dot_protobuf_dot_db__pb2.GetReq.SerializeToString,
response_deserializer=prodisdb_dot_protobuf_dot_db__pb2.GetResp.FromString,
)
self.Put = channel.unary_unary(
'/prodisdb.protobuf.Db/Put',
request_serializer=prodisdb_dot_protobuf_dot_db__pb2.PutReq.SerializeToString,
response_deserializer=prodisdb_dot_protobuf_dot_db__pb2.PutResp.FromString,
)
self.Delete = channel.unary_unary(
'/prodisdb.protobuf.Db/Delete',
request_serializer=prodisdb_dot_protobuf_dot_db__pb2.DelReq.SerializeToString,
response_deserializer=prodisdb_dot_protobuf_dot_db__pb2.DelResp.FromString,
)
class DbServicer(object):
def Get(self, request, context):
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def Put(self, request, context):
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def Delete(self, request, context):
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_DbServicer_to_server(servicer, server):
rpc_method_handlers = {
'Get': grpc.unary_unary_rpc_method_handler(
servicer.Get,
request_deserializer=prodisdb_dot_protobuf_dot_db__pb2.GetReq.FromString,
response_serializer=prodisdb_dot_protobuf_dot_db__pb2.GetResp.SerializeToString,
),
'Put': grpc.unary_unary_rpc_method_handler(
servicer.Put,
request_deserializer=prodisdb_dot_protobuf_dot_db__pb2.PutReq.FromString,
response_serializer=prodisdb_dot_protobuf_dot_db__pb2.PutResp.SerializeToString,
),
'Delete': grpc.unary_unary_rpc_method_handler(
servicer.Delete,
request_deserializer=prodisdb_dot_protobuf_dot_db__pb2.DelReq.FromString,
response_serializer=prodisdb_dot_protobuf_dot_db__pb2.DelResp.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'prodisdb.protobuf.Db', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
syntax = "proto2";
package prodisdb.protobuf;
option go_package = "gitlab.com/prodisdb/protobuf/options";
option csharp_namespace = "ProdisDB.Protobuf";
option java_package = "com.prodisdb.protobuf";
option objc_class_prefix = "PDB";
import "google/protobuf/descriptor.proto";
// These options should be used during schema definition,
// applying them to some of the fields in protobuf
message FieldOptions {
optional bool key = 1;
}
extend google.protobuf.FieldOptions {
optional FieldOptions options = 99999;
}
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: prodisdb/protobuf/options.proto
import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
from google.protobuf import descriptor_pb2
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2
DESCRIPTOR = _descriptor.FileDescriptor(
name='prodisdb/protobuf/options.proto',
package='prodisdb.protobuf',
syntax='proto2',
serialized_pb=_b('\n\x1fprodisdb/protobuf/options.proto\x12\x11prodisdb.protobuf\x1a google/protobuf/descriptor.proto\"\x1b\n\x0c\x46ieldOptions\x12\x0b\n\x03key\x18\x01 \x01(\x08:Q\n\x07options\x12\x1d.google.protobuf.FieldOptions\x18\x9f\x8d\x06 \x01(\x0b\x32\x1f.prodisdb.protobuf.FieldOptionsBW\n\x15\x63om.prodisdb.protobufZ$gitlab.com/prodisdb/protobuf/options\xa2\x02\x03PDB\xaa\x02\x11ProdisDB.Protobuf')
,
dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,])
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
OPTIONS_FIELD_NUMBER = 99999
options = _descriptor.FieldDescriptor(
name='options', full_name='prodisdb.protobuf.options', index=0,
number=99999, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=True, extension_scope=None,
options=None)
_FIELDOPTIONS = _descriptor.Descriptor(
name='FieldOptions',
full_name='prodisdb.protobuf.FieldOptions',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='key', full_name='prodisdb.protobuf.FieldOptions.key', index=0,
number=1, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=88,
serialized_end=115,
)
DESCRIPTOR.message_types_by_name['FieldOptions'] = _FIELDOPTIONS
DESCRIPTOR.extensions_by_name['options'] = options
FieldOptions = _reflection.GeneratedProtocolMessageType('FieldOptions', (_message.Message,), dict(
DESCRIPTOR = _FIELDOPTIONS,
__module__ = 'prodisdb.protobuf.options_pb2'
# @@protoc_insertion_point(class_scope:prodisdb.protobuf.FieldOptions)
))
_sym_db.RegisterMessage(FieldOptions)
options.message_type = _FIELDOPTIONS
google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(options)
DESCRIPTOR.has_options = True
DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\025com.prodisdb.protobufZ$gitlab.com/prodisdb/protobuf/options\242\002\003PDB\252\002\021ProdisDB.Protobuf'))
try:
# THESE ELEMENTS WILL BE DEPRECATED.
# Please use the generated *_pb2_grpc.py files instead.
import grpc
from grpc.beta import implementations as beta_implementations
from grpc.beta import interfaces as beta_interfaces
from grpc.framework.common import cardinality
from grpc.framework.interfaces.face import utilities as face_utilities
except ImportError:
pass
# @@protoc_insertion_point(module_scope)
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
import grpc
import grpc
from prodisdb.protobuf import db_pb2, db_pb2_grpc
import test_pb2
from google.protobuf import any_pb2
def run():
channel = grpc.insecure_channel('localhost:50051')
stub = db_pb2_grpc.DbStub(channel)
to_serialize = test_pb2.Test(
field_one_int = 123,
field_two_str = "my_string",
field_three_bool = True
)
serializable = any_pb2.Any()
serializable.Pack(to_serialize)
print (serializable.TypeName())
stub.Put(db_pb2.PutReq(
serializable = serializable
))
if __name__ == '__main__':
run()
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: test.proto
import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
from google.protobuf import descriptor_pb2
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from prodisdb.protobuf import options_pb2 as prodisdb_dot_protobuf_dot_options__pb2
DESCRIPTOR = _descriptor.FileDescriptor(
name='test.proto',
package='test',
syntax='proto3',
serialized_pb=_b('\n\ntest.proto\x12\x04test\x1a\x1fprodisdb/protobuf/options.proto\"p\n\x04Test\x12\x1d\n\rfield_one_int\x18\x01 \x01(\x05\x42\x06\xfa\xe9\x30\x02\x08\x01\x12\x15\n\rfield_two_str\x18\x02 \x01(\t\x12\x18\n\x10\x66ield_three_bool\x18\x03 \x01(\x08\x12\x18\n\x10\x66ield_four_bytes\x18\x04 \x01(\x0c\x62\x06proto3')
,
dependencies=[prodisdb_dot_protobuf_dot_options__pb2.DESCRIPTOR,])
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
_TEST = _descriptor.Descriptor(
name='Test',
full_name='test.Test',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='field_one_int', full_name='test.Test.field_one_int', index=0,
number=1, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=_descriptor._ParseOptions(descriptor_pb2.FieldOptions(), _b('\372\3510\002\010\001'))),
_descriptor.FieldDescriptor(
name='field_two_str', full_name='test.Test.field_two_str', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='field_three_bool', full_name='test.Test.field_three_bool', index=2,
number=3, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='field_four_bytes', full_name='test.Test.field_four_bytes', index=3,
number=4, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=53,
serialized_end=165,
)
DESCRIPTOR.message_types_by_name['Test'] = _TEST
Test = _reflection.GeneratedProtocolMessageType('Test', (_message.Message,), dict(
DESCRIPTOR = _TEST,
__module__ = 'test_pb2'
# @@protoc_insertion_point(class_scope:test.Test)
))
_sym_db.RegisterMessage(Test)
_TEST.fields_by_name['field_one_int'].has_options = True
_TEST.fields_by_name['field_one_int']._options = _descriptor._ParseOptions(descriptor_pb2.FieldOptions(), _b('\372\3510\002\010\001'))
try:
# THESE ELEMENTS WILL BE DEPRECATED.
# Please use the generated *_pb2_grpc.py files instead.
import grpc
from grpc.beta import implementations as beta_implementations
from grpc.beta import interfaces as beta_interfaces
from grpc.framework.common import cardinality
from grpc.framework.interfaces.face import utilities as face_utilities
except ImportError:
pass
# @@protoc_insertion_point(module_scope)
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
import grpc
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment