From ce56953b24e3173432f893c8429f1875ca91c8fe Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Fri, 3 Jun 2016 10:34:09 -0700 Subject: [PATCH] Various example/benchmarking code (#16) * initial echo client/server examples * registered and unregistered versions of the example client * ignore pyc files * cpp echo code, flag to build examples * threaded server example --- .gitignore | 3 + examples/echo/echo-client/Main.hs | 37 +++ examples/echo/echo-cpp/Makefile | 10 + examples/echo/echo-cpp/echo-client | Bin 0 -> 141744 bytes examples/echo/echo-cpp/echo-client.cc | 48 +++ examples/echo/echo-cpp/echo-server | Bin 0 -> 141664 bytes examples/echo/echo-cpp/echo-server.cc | 34 ++ examples/echo/echo-cpp/echo.grpc.pb.cc | 59 ++++ examples/echo/echo-cpp/echo.grpc.pb.h | 103 ++++++ examples/echo/echo-cpp/echo.pb.cc | 384 +++++++++++++++++++++++ examples/echo/echo-cpp/echo.pb.h | 183 +++++++++++ examples/echo/echo-python/echo_client.py | 13 + examples/echo/echo-python/echo_pb2.py | 118 +++++++ examples/echo/echo-python/echo_server.py | 20 ++ examples/echo/echo-server/Main.hs | 64 ++++ examples/echo/echo.proto | 11 + grpc-haskell.cabal | 34 ++ src/Network/GRPC/LowLevel.hs | 4 +- src/Network/GRPC/LowLevel/Call.hs | 4 + src/Network/GRPC/LowLevel/Server.hs | 8 +- tests/LowLevelTests.hs | 4 +- 21 files changed, 1135 insertions(+), 6 deletions(-) create mode 100644 examples/echo/echo-client/Main.hs create mode 100644 examples/echo/echo-cpp/Makefile create mode 100755 examples/echo/echo-cpp/echo-client create mode 100644 examples/echo/echo-cpp/echo-client.cc create mode 100755 examples/echo/echo-cpp/echo-server create mode 100644 examples/echo/echo-cpp/echo-server.cc create mode 100644 examples/echo/echo-cpp/echo.grpc.pb.cc create mode 100644 examples/echo/echo-cpp/echo.grpc.pb.h create mode 100644 examples/echo/echo-cpp/echo.pb.cc create mode 100644 examples/echo/echo-cpp/echo.pb.h create mode 100644 examples/echo/echo-python/echo_client.py create mode 100644 examples/echo/echo-python/echo_pb2.py create mode 100644 examples/echo/echo-python/echo_server.py create mode 100644 examples/echo/echo-server/Main.hs create mode 100644 examples/echo/echo.proto diff --git a/.gitignore b/.gitignore index 99ed843..50fbd7a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ dist .stack-work/ +*.pyc +*.pyo +*.o diff --git a/examples/echo/echo-client/Main.hs b/examples/echo/echo-client/Main.hs new file mode 100644 index 0000000..f6377cb --- /dev/null +++ b/examples/echo/echo-client/Main.hs @@ -0,0 +1,37 @@ +{-# LANGUAGE OverloadedStrings #-} + +import Control.Concurrent (threadDelay) +import Control.Monad (forever) +import Data.ByteString () +import qualified Data.Map as M +import Network.GRPC.LowLevel + +echoMethod :: MethodName +echoMethod = MethodName "/echo.Echo/DoEcho" + +ntimes :: Int -> IO () -> IO () +ntimes 1 f = f +ntimes n f = f >> (ntimes (n-1) f) + +unregClient :: IO () +unregClient = do + withGRPC $ \grpc -> + withClient grpc (ClientConfig "localhost" 50051) $ \client -> + ntimes 100000 $ do + reqResult <- clientRequest client echoMethod "localhost:50051" 1 "hi" M.empty + case reqResult of + Left x -> error $ "Got client error: " ++ show x + Right resp -> return () + +regClient :: IO () +regClient = do + withGRPC $ \grpc -> + withClient grpc (ClientConfig "localhost" 50051) $ \client -> ntimes 100000 $ do + regMethod <- clientRegisterMethod client echoMethod "localhost:50051" Normal + reqResult <- clientRegisteredRequest client regMethod 1 "hi" M.empty + case reqResult of + Left x -> error $ "Got client error: " ++ show x + Right resp -> return () + +main :: IO () +main = regClient diff --git a/examples/echo/echo-cpp/Makefile b/examples/echo/echo-cpp/Makefile new file mode 100644 index 0000000..63df926 --- /dev/null +++ b/examples/echo/echo-cpp/Makefile @@ -0,0 +1,10 @@ +CXX = clang++ +CXXFLAGS += -std=c++11 +CPPFLAGS += -I/usr/local/include -pthread +LDFLAGS += -L/usr/local/lib -lgrpc++_unsecure -lgrpc -lprotobuf -lpthread -ldl + +echo-server: echo.pb.o echo.grpc.pb.o echo-server.o + clang++ $^ $(LDFLAGS) -o $@ + +echo-client: echo.pb.o echo.grpc.pb.o echo-client.o + clang++ $^ $(LDFLAGS) -o $@ diff --git a/examples/echo/echo-cpp/echo-client b/examples/echo/echo-cpp/echo-client new file mode 100755 index 0000000000000000000000000000000000000000..6956847dcff479089a29966125468bbf9a4a1ed8 GIT binary patch literal 141744 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 +#include + +#include + +#include "echo.grpc.pb.h" + +using namespace std; + +using grpc::Channel; +using grpc::ClientContext; +using grpc::Status; +using echo::EchoRequest; +using echo::Echo; + +class EchoClient { +public: + EchoClient(shared_ptr chan) : stub_(Echo::NewStub(chan)) {} + + Status DoEcho(const string& msg){ + EchoRequest req; + req.set_message(msg); + + EchoRequest resp; + + ClientContext ctx; + + return stub_->DoEcho(&ctx, req, &resp); + } + +private: + unique_ptr stub_; +}; + +int main(){ + EchoClient client(grpc::CreateChannel("localhost:50051", + grpc::InsecureChannelCredentials())); + string msg("hi"); + for(int i = 0; i < 100000; i++){ + Status status = client.DoEcho(msg); + if(!status.ok()){ + cout<<"Error: "<Hh+(4!TN~H>#q-{znr3r1K1&yXo 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 + +#include +#include "echo.grpc.pb.h" + +using namespace std; + +using grpc::Server; +using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::Status; + +using echo::EchoRequest; +using echo::Echo; + +class EchoServiceImpl final : public Echo::Service { + Status DoEcho(ServerContext* ctx, const EchoRequest* req, + EchoRequest* resp) override { + resp->set_message(req->message()); + return Status::OK; + } +}; + +int main(){ + string server_address("localhost:50051"); + EchoServiceImpl service; + + ServerBuilder builder; + builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); + builder.RegisterService(&service); + unique_ptr server(builder.BuildAndStart()); + server->Wait(); + return 0; +} diff --git a/examples/echo/echo-cpp/echo.grpc.pb.cc b/examples/echo/echo-cpp/echo.grpc.pb.cc new file mode 100644 index 0000000..cc65070 --- /dev/null +++ b/examples/echo/echo-cpp/echo.grpc.pb.cc @@ -0,0 +1,59 @@ +// Generated by the gRPC protobuf plugin. +// If you make any local change, they will be lost. +// source: echo.proto + +#include "echo.pb.h" +#include "echo.grpc.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +namespace echo { + +static const char* Echo_method_names[] = { + "/echo.Echo/DoEcho", +}; + +std::unique_ptr< Echo::Stub> Echo::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) { + std::unique_ptr< Echo::Stub> stub(new Echo::Stub(channel)); + return stub; +} + +Echo::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel) + : channel_(channel), rpcmethod_DoEcho_(Echo_method_names[0], ::grpc::RpcMethod::NORMAL_RPC, channel) + {} + +::grpc::Status Echo::Stub::DoEcho(::grpc::ClientContext* context, const ::echo::EchoRequest& request, ::echo::EchoRequest* response) { + return ::grpc::BlockingUnaryCall(channel_.get(), rpcmethod_DoEcho_, context, request, response); +} + +::grpc::ClientAsyncResponseReader< ::echo::EchoRequest>* Echo::Stub::AsyncDoEchoRaw(::grpc::ClientContext* context, const ::echo::EchoRequest& request, ::grpc::CompletionQueue* cq) { + return new ::grpc::ClientAsyncResponseReader< ::echo::EchoRequest>(channel_.get(), cq, rpcmethod_DoEcho_, context, request); +} + +Echo::Service::Service() { + AddMethod(new ::grpc::RpcServiceMethod( + Echo_method_names[0], + ::grpc::RpcMethod::NORMAL_RPC, + new ::grpc::RpcMethodHandler< Echo::Service, ::echo::EchoRequest, ::echo::EchoRequest>( + std::mem_fn(&Echo::Service::DoEcho), this))); +} + +Echo::Service::~Service() { +} + +::grpc::Status Echo::Service::DoEcho(::grpc::ServerContext* context, const ::echo::EchoRequest* request, ::echo::EchoRequest* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + + +} // namespace echo + diff --git a/examples/echo/echo-cpp/echo.grpc.pb.h b/examples/echo/echo-cpp/echo.grpc.pb.h new file mode 100644 index 0000000..df1c128 --- /dev/null +++ b/examples/echo/echo-cpp/echo.grpc.pb.h @@ -0,0 +1,103 @@ +// Generated by the gRPC protobuf plugin. +// If you make any local change, they will be lost. +// source: echo.proto +#ifndef GRPC_echo_2eproto__INCLUDED +#define GRPC_echo_2eproto__INCLUDED + +#include "echo.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace grpc { +class CompletionQueue; +class RpcService; +class ServerCompletionQueue; +class ServerContext; +} // namespace grpc + +namespace echo { + +class Echo GRPC_FINAL { + public: + class StubInterface { + public: + virtual ~StubInterface() {} + virtual ::grpc::Status DoEcho(::grpc::ClientContext* context, const ::echo::EchoRequest& request, ::echo::EchoRequest* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::echo::EchoRequest>> AsyncDoEcho(::grpc::ClientContext* context, const ::echo::EchoRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::echo::EchoRequest>>(AsyncDoEchoRaw(context, request, cq)); + } + private: + virtual ::grpc::ClientAsyncResponseReaderInterface< ::echo::EchoRequest>* AsyncDoEchoRaw(::grpc::ClientContext* context, const ::echo::EchoRequest& request, ::grpc::CompletionQueue* cq) = 0; + }; + class Stub GRPC_FINAL : public StubInterface { + public: + Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel); + ::grpc::Status DoEcho(::grpc::ClientContext* context, const ::echo::EchoRequest& request, ::echo::EchoRequest* response) GRPC_OVERRIDE; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::echo::EchoRequest>> AsyncDoEcho(::grpc::ClientContext* context, const ::echo::EchoRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::echo::EchoRequest>>(AsyncDoEchoRaw(context, request, cq)); + } + + private: + std::shared_ptr< ::grpc::ChannelInterface> channel_; + ::grpc::ClientAsyncResponseReader< ::echo::EchoRequest>* AsyncDoEchoRaw(::grpc::ClientContext* context, const ::echo::EchoRequest& request, ::grpc::CompletionQueue* cq) GRPC_OVERRIDE; + const ::grpc::RpcMethod rpcmethod_DoEcho_; + }; + static std::unique_ptr NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); + + class Service : public ::grpc::Service { + public: + Service(); + virtual ~Service(); + virtual ::grpc::Status DoEcho(::grpc::ServerContext* context, const ::echo::EchoRequest* request, ::echo::EchoRequest* response); + }; + template + class WithAsyncMethod_DoEcho : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(Service *service) {} + public: + WithAsyncMethod_DoEcho() { + ::grpc::Service::MarkMethodAsync(0); + } + ~WithAsyncMethod_DoEcho() GRPC_OVERRIDE { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status DoEcho(::grpc::ServerContext* context, const ::echo::EchoRequest* request, ::echo::EchoRequest* response) GRPC_FINAL GRPC_OVERRIDE { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestDoEcho(::grpc::ServerContext* context, ::echo::EchoRequest* request, ::grpc::ServerAsyncResponseWriter< ::echo::EchoRequest>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + typedef WithAsyncMethod_DoEcho AsyncService; + template + class WithGenericMethod_DoEcho : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(Service *service) {} + public: + WithGenericMethod_DoEcho() { + ::grpc::Service::MarkMethodGeneric(0); + } + ~WithGenericMethod_DoEcho() GRPC_OVERRIDE { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status DoEcho(::grpc::ServerContext* context, const ::echo::EchoRequest* request, ::echo::EchoRequest* response) GRPC_FINAL GRPC_OVERRIDE { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; +}; + +} // namespace echo + + +#endif // GRPC_echo_2eproto__INCLUDED diff --git a/examples/echo/echo-cpp/echo.pb.cc b/examples/echo/echo-cpp/echo.pb.cc new file mode 100644 index 0000000..c68cac1 --- /dev/null +++ b/examples/echo/echo-cpp/echo.pb.cc @@ -0,0 +1,384 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: echo.proto + +#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION +#include "echo.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace echo { + +namespace { + +const ::google::protobuf::Descriptor* EchoRequest_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + EchoRequest_reflection_ = NULL; + +} // namespace + + +void protobuf_AssignDesc_echo_2eproto() { + protobuf_AddDesc_echo_2eproto(); + const ::google::protobuf::FileDescriptor* file = + ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName( + "echo.proto"); + GOOGLE_CHECK(file != NULL); + EchoRequest_descriptor_ = file->message_type(0); + static const int EchoRequest_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EchoRequest, message_), + }; + EchoRequest_reflection_ = + ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection( + EchoRequest_descriptor_, + EchoRequest::default_instance_, + EchoRequest_offsets_, + -1, + -1, + -1, + sizeof(EchoRequest), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EchoRequest, _internal_metadata_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EchoRequest, _is_default_instance_)); +} + +namespace { + +GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_); +inline void protobuf_AssignDescriptorsOnce() { + ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_, + &protobuf_AssignDesc_echo_2eproto); +} + +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + EchoRequest_descriptor_, &EchoRequest::default_instance()); +} + +} // namespace + +void protobuf_ShutdownFile_echo_2eproto() { + delete EchoRequest::default_instance_; + delete EchoRequest_reflection_; +} + +void protobuf_AddDesc_echo_2eproto() { + static bool already_here = false; + if (already_here) return; + already_here = true; + GOOGLE_PROTOBUF_VERIFY_VERSION; + + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + "\n\necho.proto\022\004echo\"\036\n\013EchoRequest\022\017\n\007mes" + "sage\030\001 \001(\t28\n\004Echo\0220\n\006DoEcho\022\021.echo.Echo" + "Request\032\021.echo.EchoRequest\"\000b\006proto3", 116); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "echo.proto", &protobuf_RegisterTypes); + EchoRequest::default_instance_ = new EchoRequest(); + EchoRequest::default_instance_->InitAsDefaultInstance(); + ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_echo_2eproto); +} + +// Force AddDescriptors() to be called at static initialization time. +struct StaticDescriptorInitializer_echo_2eproto { + StaticDescriptorInitializer_echo_2eproto() { + protobuf_AddDesc_echo_2eproto(); + } +} static_descriptor_initializer_echo_2eproto_; + +namespace { + +static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD; +static void MergeFromFail(int line) { + GOOGLE_CHECK(false) << __FILE__ << ":" << line; +} + +} // namespace + + +// =================================================================== + +#if !defined(_MSC_VER) || _MSC_VER >= 1900 +const int EchoRequest::kMessageFieldNumber; +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 + +EchoRequest::EchoRequest() + : ::google::protobuf::Message(), _internal_metadata_(NULL) { + SharedCtor(); + // @@protoc_insertion_point(constructor:echo.EchoRequest) +} + +void EchoRequest::InitAsDefaultInstance() { + _is_default_instance_ = true; +} + +EchoRequest::EchoRequest(const EchoRequest& from) + : ::google::protobuf::Message(), + _internal_metadata_(NULL) { + SharedCtor(); + MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:echo.EchoRequest) +} + +void EchoRequest::SharedCtor() { + _is_default_instance_ = false; + ::google::protobuf::internal::GetEmptyString(); + _cached_size_ = 0; + message_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + +EchoRequest::~EchoRequest() { + // @@protoc_insertion_point(destructor:echo.EchoRequest) + SharedDtor(); +} + +void EchoRequest::SharedDtor() { + message_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (this != default_instance_) { + } +} + +void EchoRequest::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* EchoRequest::descriptor() { + protobuf_AssignDescriptorsOnce(); + return EchoRequest_descriptor_; +} + +const EchoRequest& EchoRequest::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_echo_2eproto(); + return *default_instance_; +} + +EchoRequest* EchoRequest::default_instance_ = NULL; + +EchoRequest* EchoRequest::New(::google::protobuf::Arena* arena) const { + EchoRequest* n = new EchoRequest; + if (arena != NULL) { + arena->Own(n); + } + return n; +} + +void EchoRequest::Clear() { + message_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + +bool EchoRequest::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure + ::google::protobuf::uint32 tag; + // @@protoc_insertion_point(parse_start:echo.EchoRequest) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional string message = 1; + case 1: { + if (tag == 10) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_message())); + DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->message().data(), this->message().length(), + ::google::protobuf::internal::WireFormatLite::PARSE, + "echo.EchoRequest.message")); + } else { + goto handle_unusual; + } + if (input->ExpectAtEnd()) goto success; + break; + } + + default: { + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + goto success; + } + DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag)); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:echo.EchoRequest) + return true; +failure: + // @@protoc_insertion_point(parse_failure:echo.EchoRequest) + return false; +#undef DO_ +} + +void EchoRequest::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:echo.EchoRequest) + // optional string message = 1; + if (this->message().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->message().data(), this->message().length(), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "echo.EchoRequest.message"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 1, this->message(), output); + } + + // @@protoc_insertion_point(serialize_end:echo.EchoRequest) +} + +::google::protobuf::uint8* EchoRequest::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:echo.EchoRequest) + // optional string message = 1; + if (this->message().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->message().data(), this->message().length(), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "echo.EchoRequest.message"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->message(), target); + } + + // @@protoc_insertion_point(serialize_to_array_end:echo.EchoRequest) + return target; +} + +int EchoRequest::ByteSize() const { + int total_size = 0; + + // optional string message = 1; + if (this->message().size() > 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->message()); + } + + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void EchoRequest::MergeFrom(const ::google::protobuf::Message& from) { + if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + const EchoRequest* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void EchoRequest::MergeFrom(const EchoRequest& from) { + if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (from.message().size() > 0) { + + message_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.message_); + } +} + +void EchoRequest::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void EchoRequest::CopyFrom(const EchoRequest& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool EchoRequest::IsInitialized() const { + + return true; +} + +void EchoRequest::Swap(EchoRequest* other) { + if (other == this) return; + InternalSwap(other); +} +void EchoRequest::InternalSwap(EchoRequest* other) { + message_.Swap(&other->message_); + _internal_metadata_.Swap(&other->_internal_metadata_); + std::swap(_cached_size_, other->_cached_size_); +} + +::google::protobuf::Metadata EchoRequest::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = EchoRequest_descriptor_; + metadata.reflection = EchoRequest_reflection_; + return metadata; +} + +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// EchoRequest + +// optional string message = 1; +void EchoRequest::clear_message() { + message_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + const ::std::string& EchoRequest::message() const { + // @@protoc_insertion_point(field_get:echo.EchoRequest.message) + return message_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void EchoRequest::set_message(const ::std::string& value) { + + message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:echo.EchoRequest.message) +} + void EchoRequest::set_message(const char* value) { + + message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:echo.EchoRequest.message) +} + void EchoRequest::set_message(const char* value, size_t size) { + + message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:echo.EchoRequest.message) +} + ::std::string* EchoRequest::mutable_message() { + + // @@protoc_insertion_point(field_mutable:echo.EchoRequest.message) + return message_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* EchoRequest::release_message() { + + return message_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void EchoRequest::set_allocated_message(::std::string* message) { + if (message != NULL) { + + } else { + + } + message_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), message); + // @@protoc_insertion_point(field_set_allocated:echo.EchoRequest.message) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS + +// @@protoc_insertion_point(namespace_scope) + +} // namespace echo + +// @@protoc_insertion_point(global_scope) diff --git a/examples/echo/echo-cpp/echo.pb.h b/examples/echo/echo-cpp/echo.pb.h new file mode 100644 index 0000000..089f94a --- /dev/null +++ b/examples/echo/echo-cpp/echo.pb.h @@ -0,0 +1,183 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: echo.proto + +#ifndef PROTOBUF_echo_2eproto__INCLUDED +#define PROTOBUF_echo_2eproto__INCLUDED + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 3000000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace echo { + +// Internal implementation detail -- do not call these. +void protobuf_AddDesc_echo_2eproto(); +void protobuf_AssignDesc_echo_2eproto(); +void protobuf_ShutdownFile_echo_2eproto(); + +class EchoRequest; + +// =================================================================== + +class EchoRequest : public ::google::protobuf::Message { + public: + EchoRequest(); + virtual ~EchoRequest(); + + EchoRequest(const EchoRequest& from); + + inline EchoRequest& operator=(const EchoRequest& from) { + CopyFrom(from); + return *this; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const EchoRequest& default_instance(); + + void Swap(EchoRequest* other); + + // implements Message ---------------------------------------------- + + inline EchoRequest* New() const { return New(NULL); } + + EchoRequest* New(::google::protobuf::Arena* arena) const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const EchoRequest& from); + void MergeFrom(const EchoRequest& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + void InternalSwap(EchoRequest* other); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return _internal_metadata_.arena(); + } + inline void* MaybeArenaPtr() const { + return _internal_metadata_.raw_arena_ptr(); + } + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional string message = 1; + void clear_message(); + static const int kMessageFieldNumber = 1; + const ::std::string& message() const; + void set_message(const ::std::string& value); + void set_message(const char* value); + void set_message(const char* value, size_t size); + ::std::string* mutable_message(); + ::std::string* release_message(); + void set_allocated_message(::std::string* message); + + // @@protoc_insertion_point(class_scope:echo.EchoRequest) + private: + + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; + bool _is_default_instance_; + ::google::protobuf::internal::ArenaStringPtr message_; + mutable int _cached_size_; + friend void protobuf_AddDesc_echo_2eproto(); + friend void protobuf_AssignDesc_echo_2eproto(); + friend void protobuf_ShutdownFile_echo_2eproto(); + + void InitAsDefaultInstance(); + static EchoRequest* default_instance_; +}; +// =================================================================== + + +// =================================================================== + +#if !PROTOBUF_INLINE_NOT_IN_HEADERS +// EchoRequest + +// optional string message = 1; +inline void EchoRequest::clear_message() { + message_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline const ::std::string& EchoRequest::message() const { + // @@protoc_insertion_point(field_get:echo.EchoRequest.message) + return message_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void EchoRequest::set_message(const ::std::string& value) { + + message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:echo.EchoRequest.message) +} +inline void EchoRequest::set_message(const char* value) { + + message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:echo.EchoRequest.message) +} +inline void EchoRequest::set_message(const char* value, size_t size) { + + message_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:echo.EchoRequest.message) +} +inline ::std::string* EchoRequest::mutable_message() { + + // @@protoc_insertion_point(field_mutable:echo.EchoRequest.message) + return message_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline ::std::string* EchoRequest::release_message() { + + return message_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void EchoRequest::set_allocated_message(::std::string* message) { + if (message != NULL) { + + } else { + + } + message_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), message); + // @@protoc_insertion_point(field_set_allocated:echo.EchoRequest.message) +} + +#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS + +// @@protoc_insertion_point(namespace_scope) + +} // namespace echo + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_echo_2eproto__INCLUDED diff --git a/examples/echo/echo-python/echo_client.py b/examples/echo/echo-python/echo_client.py new file mode 100644 index 0000000..46fc45e --- /dev/null +++ b/examples/echo/echo-python/echo_client.py @@ -0,0 +1,13 @@ +from grpc.beta import implementations + +import echo_pb2 + +def main(): + for _ in xrange(1000): + channel = implementations.insecure_channel('localhost', 50051) + stub = echo_pb2.beta_create_Echo_stub(channel) + message = echo_pb2.EchoRequest(message='foo') + response = stub.DoEcho(message, 15) + +if __name__ == '__main__': + main() diff --git a/examples/echo/echo-python/echo_pb2.py b/examples/echo/echo-python/echo_pb2.py new file mode 100644 index 0000000..3fc37b0 --- /dev/null +++ b/examples/echo/echo-python/echo_pb2.py @@ -0,0 +1,118 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: echo.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() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='echo.proto', + package='echo', + syntax='proto3', + serialized_pb=_b('\n\necho.proto\x12\x04\x65\x63ho\"\x1e\n\x0b\x45\x63hoRequest\x12\x0f\n\x07message\x18\x01 \x01(\t28\n\x04\x45\x63ho\x12\x30\n\x06\x44oEcho\x12\x11.echo.EchoRequest\x1a\x11.echo.EchoRequest\"\x00\x62\x06proto3') +) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + + + + +_ECHOREQUEST = _descriptor.Descriptor( + name='EchoRequest', + full_name='echo.EchoRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='message', full_name='echo.EchoRequest.message', index=0, + number=1, 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), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=20, + serialized_end=50, +) + +DESCRIPTOR.message_types_by_name['EchoRequest'] = _ECHOREQUEST + +EchoRequest = _reflection.GeneratedProtocolMessageType('EchoRequest', (_message.Message,), dict( + DESCRIPTOR = _ECHOREQUEST, + __module__ = 'echo_pb2' + # @@protoc_insertion_point(class_scope:echo.EchoRequest) + )) +_sym_db.RegisterMessage(EchoRequest) + + +import abc +from grpc.beta import implementations as beta_implementations +from grpc.framework.common import cardinality +from grpc.framework.interfaces.face import utilities as face_utilities + +class BetaEchoServicer(object): + """""" + __metaclass__ = abc.ABCMeta + @abc.abstractmethod + def DoEcho(self, request, context): + raise NotImplementedError() + +class BetaEchoStub(object): + """The interface to which stubs will conform.""" + __metaclass__ = abc.ABCMeta + @abc.abstractmethod + def DoEcho(self, request, timeout): + raise NotImplementedError() + DoEcho.future = None + +def beta_create_Echo_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None): + import echo_pb2 + import echo_pb2 + request_deserializers = { + ('echo.Echo', 'DoEcho'): echo_pb2.EchoRequest.FromString, + } + response_serializers = { + ('echo.Echo', 'DoEcho'): echo_pb2.EchoRequest.SerializeToString, + } + method_implementations = { + ('echo.Echo', 'DoEcho'): face_utilities.unary_unary_inline(servicer.DoEcho), + } + server_options = beta_implementations.server_options(request_deserializers=request_deserializers, response_serializers=response_serializers, thread_pool=pool, thread_pool_size=pool_size, default_timeout=default_timeout, maximum_timeout=maximum_timeout) + return beta_implementations.server(method_implementations, options=server_options) + +def beta_create_Echo_stub(channel, host=None, metadata_transformer=None, pool=None, pool_size=None): + import echo_pb2 + import echo_pb2 + request_serializers = { + ('echo.Echo', 'DoEcho'): echo_pb2.EchoRequest.SerializeToString, + } + response_deserializers = { + ('echo.Echo', 'DoEcho'): echo_pb2.EchoRequest.FromString, + } + cardinalities = { + 'DoEcho': cardinality.Cardinality.UNARY_UNARY, + } + stub_options = beta_implementations.stub_options(host=host, metadata_transformer=metadata_transformer, request_serializers=request_serializers, response_deserializers=response_deserializers, thread_pool=pool, thread_pool_size=pool_size) + return beta_implementations.dynamic_stub(channel, 'echo.Echo', cardinalities, options=stub_options) +# @@protoc_insertion_point(module_scope) diff --git a/examples/echo/echo-python/echo_server.py b/examples/echo/echo-python/echo_server.py new file mode 100644 index 0000000..c792486 --- /dev/null +++ b/examples/echo/echo-python/echo_server.py @@ -0,0 +1,20 @@ +from grpc.beta import implementations + +import echo_pb2 +import time + +class Echo(echo_pb2.BetaEchoServicer): + def DoEcho(self, request, context): + return echo_pb2.EchoRequest(message=request.message) + +def main(): + server = echo_pb2.beta_create_Echo_server(Echo()) + server.add_insecure_port('[::]:50051') + server.start() + try: + time.sleep(600) + except KeyboardInterrupt: + server.stop(0) + +if __name__ == '__main__': + main() diff --git a/examples/echo/echo-server/Main.hs b/examples/echo/echo-server/Main.hs new file mode 100644 index 0000000..30d8b2b --- /dev/null +++ b/examples/echo/echo-server/Main.hs @@ -0,0 +1,64 @@ +{-# LANGUAGE OverloadedStrings #-} + +import Control.Concurrent.Async (async, wait) +import Control.Monad (forever) +import Data.ByteString (ByteString) +import qualified Data.Map as M +import Network.GRPC.LowLevel + + +serverMeta :: MetadataMap +serverMeta = M.fromList [("test_meta", "test_meta_value")] + +handler :: ByteString -> MetadataMap -> MethodName + -> IO (ByteString, MetadataMap, StatusDetails) +handler reqBody reqMeta method = do + --putStrLn $ "Got request for method: " ++ show method + --putStrLn $ "Got metadata: " ++ show reqMeta + return (reqBody, serverMeta, StatusDetails "") + +unregMain :: IO () +unregMain = withGRPC $ \grpc -> do + withServer grpc (ServerConfig "localhost" 50051 []) $ \server -> forever $ do + result <- serverHandleNormalCall server 15 serverMeta handler + case result of + Left x -> putStrLn $ "handle call result error: " ++ show x + Right _ -> return () + +regMain :: IO () +regMain = withGRPC $ \grpc -> do + let methods = [(MethodName "/echo.Echo/DoEcho", Normal)] + withServer grpc (ServerConfig "localhost" 50051 methods) $ \server -> + forever $ do + let method = head (registeredMethods server) + result <- serverHandleNormalRegisteredCall server method 15 serverMeta $ + \reqBody _reqMeta -> return (reqBody, serverMeta, serverMeta, + StatusDetails "") + case result of + Left x -> putStrLn $ "registered call result error: " ++ show x + Right _ -> return () + +-- | loop to fork n times +regLoop :: Server -> RegisteredMethod -> IO () +regLoop server method = forever $ do + result <- serverHandleNormalRegisteredCall server method 15 serverMeta $ + \reqBody _reqMeta -> return (reqBody, serverMeta, serverMeta, + StatusDetails "") + case result of + Left x -> putStrLn $ "registered call result error: " ++ show x + Right _ -> return () + +regMainThreaded :: IO () +regMainThreaded = do + withGRPC $ \grpc -> do + let methods = [(MethodName "/echo.Echo/DoEcho", Normal)] + withServer grpc (ServerConfig "localhost" 50051 methods) $ \server -> do + let method = head (registeredMethods server) + tid1 <- async $ regLoop server method + tid2 <- async $ regLoop server method + wait tid1 + wait tid2 + return () + +main :: IO () +main = regMainThreaded diff --git a/examples/echo/echo.proto b/examples/echo/echo.proto new file mode 100644 index 0000000..ed192c7 --- /dev/null +++ b/examples/echo/echo.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +package echo; + +service Echo { + rpc DoEcho (EchoRequest) returns (EchoRequest) {} +} + +message EchoRequest { + string message = 1; +} diff --git a/grpc-haskell.cabal b/grpc-haskell.cabal index 9e726a9..51f2d9b 100644 --- a/grpc-haskell.cabal +++ b/grpc-haskell.cabal @@ -18,6 +18,11 @@ Flag Debug Manual: True Default: False +flag with-examples + description: Also build example executables. + manual: True + default: False + library build-depends: base ==4.8.* @@ -65,6 +70,35 @@ library CPP-Options: -DDEBUG CC-Options: -DGRPC_HASKELL_DEBUG +executable echo-server + if flag(with-examples) + build-depends: + base ==4.8.* + , bytestring == 0.10.* + , grpc-haskell + , containers ==0.5.* + , async + else + buildable: False + default-language: Haskell2010 + ghc-options: -Wall -g -threaded + hs-source-dirs: examples/echo/echo-server + main-is: Main.hs + +executable echo-client + if flag(with-examples) + build-depends: + base ==4.8.* + , bytestring == 0.10.* + , grpc-haskell + , containers ==0.5.* + else + buildable: False + default-language: Haskell2010 + ghc-options: -Wall -g -threaded + hs-source-dirs: examples/echo/echo-client + main-is: Main.hs + test-suite test build-depends: base ==4.8.* diff --git a/src/Network/GRPC/LowLevel.hs b/src/Network/GRPC/LowLevel.hs index 9023012..aa96213 100644 --- a/src/Network/GRPC/LowLevel.hs +++ b/src/Network/GRPC/LowLevel.hs @@ -22,6 +22,9 @@ GRPC , GRPCMethodType(..) , RegisteredMethod , NormalRequestResult(..) +, MetadataMap +, MethodName(..) +, StatusDetails(..) -- * Server , ServerConfig(..) @@ -53,7 +56,6 @@ GRPC , runServerUnregOps , Op(..) , OpRecvResult(..) -, StatusDetails(..) ) where diff --git a/src/Network/GRPC/LowLevel/Call.hs b/src/Network/GRPC/LowLevel/Call.hs index 5c9d885..5190e83 100644 --- a/src/Network/GRPC/LowLevel/Call.hs +++ b/src/Network/GRPC/LowLevel/Call.hs @@ -90,6 +90,10 @@ serverUnregCallGetMethodName :: ServerUnregCall -> IO MethodName serverUnregCallGetMethodName ServerUnregCall{..} = MethodName <$> C.callDetailsGetMethod callDetails +serverUnregCallGetHost :: ServerUnregCall -> IO Host +serverUnregCallGetHost ServerUnregCall{..} = + Host <$> C.callDetailsGetHost callDetails + debugClientCall :: ClientCall -> IO () {-# INLINE debugClientCall #-} #ifdef DEBUG diff --git a/src/Network/GRPC/LowLevel/Server.hs b/src/Network/GRPC/LowLevel/Server.hs index aaa124b..60a3ea0 100644 --- a/src/Network/GRPC/LowLevel/Server.hs +++ b/src/Network/GRPC/LowLevel/Server.hs @@ -35,7 +35,7 @@ data ServerConfig = -- how this is used. Setting to "localhost" works fine in tests. port :: Int, -- ^ Port to listen for requests on. - methodsToRegister :: [(MethodName, Host, GRPCMethodType)] + methodsToRegister :: [(MethodName, GRPCMethodType)] -- ^ List of (method name, method host, method type) tuples -- specifying all methods to register. You can also handle -- other unregistered methods with `serverHandleNormalCall`. @@ -51,8 +51,8 @@ startServer grpc ServerConfig{..} = do cq <- createCompletionQueue grpc serverRegisterCompletionQueue server cq methods <- forM methodsToRegister $ - \(name, host, mtype) -> - serverRegisterMethod server name host mtype + \(name, mtype) -> + serverRegisterMethod server name (Host hostPort) mtype C.grpcServerStart server return $ Server server cq methods @@ -249,6 +249,8 @@ serverHandleNormalCall s@Server{..} timeLimit srvMetadata f = do requestMeta <- serverUnregCallGetMetadata call grpcDebug $ "got client metadata: " ++ show requestMeta methodName <- serverUnregCallGetMethodName call + hostName <- serverUnregCallGetHost call + grpcDebug $ "call_details host is: " ++ show hostName (respBody, respMetadata, details) <- f body requestMeta methodName let status = C.GrpcStatusOk let respOps = serverOpsSendNormalResponse diff --git a/tests/LowLevelTests.hs b/tests/LowLevelTests.hs index f5a9d4d..8022b16 100644 --- a/tests/LowLevelTests.hs +++ b/tests/LowLevelTests.hs @@ -44,7 +44,7 @@ testClientCreateDestroy = payloadLowLevelServer :: TestServer payloadLowLevelServer = TestServer $ \grpc -> do - let conf = (ServerConfig "localhost" 50051 [("/foo", "localhost", Normal)]) + let conf = (ServerConfig "localhost" 50051 [("/foo", Normal)]) withServer grpc conf $ \server -> do let method = head (registeredMethods server) result <- serverHandleNormalRegisteredCall server method 11 M.empty $ @@ -109,7 +109,7 @@ testClientRequestNoServer = testServerAwaitNoClient :: TestTree testServerAwaitNoClient = testCase "server wait times out when no client " $ do withGRPC $ \grpc -> do - let conf = (ServerConfig "localhost" 50051 [("/foo", "localhost", Normal)]) + let conf = (ServerConfig "localhost" 50051 [("/foo", Normal)]) withServer grpc conf $ \server -> do let method = head (registeredMethods server) result <- serverHandleNormalRegisteredCall server method 1 M.empty $