mirror of https://github.com/grpc/grpc.git
commit
4170a45732
126 changed files with 3452 additions and 848 deletions
@ -1,57 +1,5 @@ |
||||
--- |
||||
Language: Cpp |
||||
# BasedOnStyle: Google |
||||
AccessModifierOffset: -1 |
||||
ConstructorInitializerIndentWidth: 4 |
||||
AlignEscapedNewlinesLeft: true |
||||
AlignTrailingComments: true |
||||
AllowAllParametersOfDeclarationOnNextLine: true |
||||
AllowShortBlocksOnASingleLine: false |
||||
AllowShortIfStatementsOnASingleLine: true |
||||
AllowShortLoopsOnASingleLine: true |
||||
AllowShortFunctionsOnASingleLine: All |
||||
AlwaysBreakTemplateDeclarations: true |
||||
AlwaysBreakBeforeMultilineStrings: true |
||||
BreakBeforeBinaryOperators: false |
||||
BreakBeforeTernaryOperators: true |
||||
BreakConstructorInitializersBeforeComma: false |
||||
BinPackParameters: true |
||||
ColumnLimit: 80 |
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true |
||||
DerivePointerAlignment: true |
||||
ExperimentalAutoDetectBinPacking: false |
||||
IndentCaseLabels: true |
||||
IndentWrappedFunctionNames: false |
||||
IndentFunctionDeclarationAfterType: false |
||||
MaxEmptyLinesToKeep: 1 |
||||
KeepEmptyLinesAtTheStartOfBlocks: false |
||||
NamespaceIndentation: None |
||||
ObjCSpaceAfterProperty: false |
||||
ObjCSpaceBeforeProtocolList: false |
||||
PenaltyBreakBeforeFirstCallParameter: 1 |
||||
PenaltyBreakComment: 300 |
||||
PenaltyBreakString: 1000 |
||||
PenaltyBreakFirstLessLess: 120 |
||||
PenaltyExcessCharacter: 1000000 |
||||
PenaltyReturnTypeOnItsOwnLine: 200 |
||||
PointerAlignment: Left |
||||
SpacesBeforeTrailingComments: 2 |
||||
Cpp11BracedListStyle: true |
||||
Standard: Auto |
||||
IndentWidth: 2 |
||||
TabWidth: 8 |
||||
UseTab: Never |
||||
BreakBeforeBraces: Attach |
||||
SpacesInParentheses: false |
||||
SpacesInAngles: false |
||||
SpaceInEmptyParentheses: false |
||||
SpacesInCStyleCastParentheses: false |
||||
SpacesInContainerLiterals: true |
||||
SpaceBeforeAssignmentOperators: true |
||||
ContinuationIndentWidth: 4 |
||||
CommentPragmas: '^ IWYU pragma:' |
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] |
||||
SpaceBeforeParens: ControlStatements |
||||
DisableFormat: false |
||||
BasedOnStyle: Google |
||||
... |
||||
|
||||
|
@ -0,0 +1,60 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc++/client_context.h> |
||||
|
||||
#include "examples/tips/client.h" |
||||
|
||||
using tech::pubsub::Topic; |
||||
using tech::pubsub::PublisherService; |
||||
|
||||
namespace grpc { |
||||
namespace examples { |
||||
namespace tips { |
||||
|
||||
Client::Client(std::shared_ptr<ChannelInterface> channel) |
||||
: stub_(PublisherService::NewStub(channel)) { |
||||
} |
||||
|
||||
Status Client::CreateTopic(grpc::string topic) { |
||||
Topic request; |
||||
Topic response; |
||||
request.set_name(topic); |
||||
ClientContext context; |
||||
|
||||
return stub_->CreateTopic(&context, request, &response); |
||||
} |
||||
|
||||
} // namespace tips
|
||||
} // namespace examples
|
||||
} // namespace grpc
|
@ -0,0 +1,73 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc/grpc.h> |
||||
#include <grpc/support/log.h> |
||||
#include <google/gflags.h> |
||||
#include <grpc++/channel_interface.h> |
||||
#include <grpc++/create_channel.h> |
||||
#include <grpc++/status.h> |
||||
|
||||
#include "examples/tips/client.h" |
||||
#include "test/cpp/util/create_test_channel.h" |
||||
|
||||
DEFINE_bool(enable_ssl, true, "Whether to use ssl/tls."); |
||||
DEFINE_bool(use_prod_roots, true, "True to use SSL roots for production GFE"); |
||||
DEFINE_int32(server_port, 0, "Server port."); |
||||
DEFINE_string(server_host, "127.0.0.1", "Server host to connect to"); |
||||
DEFINE_string(server_host_override, "foo.test.google.com", |
||||
"Override the server host which is sent in HTTP header"); |
||||
|
||||
int main(int argc, char** argv) { |
||||
grpc_init(); |
||||
google::ParseCommandLineFlags(&argc, &argv, true); |
||||
gpr_log(GPR_INFO, "Start TIPS client"); |
||||
|
||||
GPR_ASSERT(FLAGS_server_port); |
||||
const int host_port_buf_size = 1024; |
||||
char host_port[host_port_buf_size]; |
||||
snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(), |
||||
FLAGS_server_port); |
||||
|
||||
std::shared_ptr<grpc::ChannelInterface> channel( |
||||
grpc::CreateTestChannel(host_port, FLAGS_server_host_override, |
||||
FLAGS_enable_ssl, FLAGS_use_prod_roots)); |
||||
|
||||
grpc::examples::tips::Client client(channel); |
||||
grpc::Status s = client.CreateTopic("test"); |
||||
GPR_ASSERT(s.IsOk()); |
||||
|
||||
channel.reset(); |
||||
grpc_shutdown(); |
||||
return 0; |
||||
} |
@ -0,0 +1,106 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc++/channel_arguments.h> |
||||
#include <grpc++/channel_interface.h> |
||||
#include <grpc++/client_context.h> |
||||
#include <grpc++/create_channel.h> |
||||
#include <grpc++/server.h> |
||||
#include <grpc++/server_builder.h> |
||||
#include <grpc++/server_context.h> |
||||
#include <grpc++/status.h> |
||||
#include <gtest/gtest.h> |
||||
|
||||
#include "examples/tips/client.h" |
||||
#include "test/core/util/port.h" |
||||
#include "test/core/util/test_config.h" |
||||
|
||||
using grpc::ChannelInterface; |
||||
|
||||
namespace grpc { |
||||
namespace testing { |
||||
namespace { |
||||
|
||||
const char kTopic[] = "test topic"; |
||||
|
||||
class PublishServiceImpl : public tech::pubsub::PublisherService::Service { |
||||
public: |
||||
Status CreateTopic(::grpc::ServerContext* context, |
||||
const ::tech::pubsub::Topic* request, |
||||
::tech::pubsub::Topic* response) override { |
||||
EXPECT_EQ(request->name(), kTopic); |
||||
return Status::OK; |
||||
} |
||||
}; |
||||
|
||||
class End2endTest : public ::testing::Test { |
||||
protected: |
||||
void SetUp() override { |
||||
int port = grpc_pick_unused_port_or_die(); |
||||
server_address_ << "localhost:" << port; |
||||
// Setup server
|
||||
ServerBuilder builder; |
||||
builder.AddPort(server_address_.str()); |
||||
builder.RegisterService(service_.service()); |
||||
server_ = builder.BuildAndStart(); |
||||
|
||||
channel_ = CreateChannel(server_address_.str(), ChannelArguments()); |
||||
} |
||||
|
||||
void TearDown() override { server_->Shutdown(); } |
||||
|
||||
std::unique_ptr<Server> server_; |
||||
std::ostringstream server_address_; |
||||
PublishServiceImpl service_; |
||||
|
||||
std::shared_ptr<ChannelInterface> channel_; |
||||
}; |
||||
|
||||
TEST_F(End2endTest, CreateTopic) { |
||||
grpc::examples::tips::Client client(channel_); |
||||
client.CreateTopic(kTopic); |
||||
} |
||||
|
||||
} // namespace
|
||||
} // namespace testing
|
||||
} // namespace grpc
|
||||
|
||||
int main(int argc, char** argv) { |
||||
grpc_test_init(argc, argv); |
||||
grpc_init(); |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
gpr_log(GPR_INFO, "Start test ..."); |
||||
int result = RUN_ALL_TESTS(); |
||||
grpc_shutdown(); |
||||
return result; |
||||
} |
@ -0,0 +1,13 @@ |
||||
syntax = "proto2"; |
||||
|
||||
package proto2; |
||||
|
||||
// An empty message that you can re-use to avoid defining duplicated empty |
||||
// messages in your project. A typical example is to use it as argument or the |
||||
// return value of a service API. For instance: |
||||
// |
||||
// service Foo { |
||||
// rpc Bar (proto2.Empty) returns (proto2.Empty) { }; |
||||
// }; |
||||
// |
||||
message Empty {} |
@ -0,0 +1,48 @@ |
||||
// Labels provide a way to associate user-defined metadata with various |
||||
// objects. Labels may be used to organize objects into non-hierarchical |
||||
// groups; think metadata tags attached to mp3s. |
||||
|
||||
syntax = "proto2"; |
||||
|
||||
package tech.label; |
||||
|
||||
// A key-value pair applied to a given object. |
||||
message Label { |
||||
// The key of a label is a syntactically valid URL (as per RFC 1738) with |
||||
// the "scheme" and initial slashes omitted and with the additional |
||||
// restrictions noted below. Each key should be globally unique. The |
||||
// "host" portion is called the "namespace" and is not necessarily |
||||
// resolvable to a network endpoint. Instead, the namespace indicates what |
||||
// system or entity defines the semantics of the label. Namespaces do not |
||||
// restrict the set of objects to which a label may be associated. |
||||
// |
||||
// Keys are defined by the following grammar: |
||||
// |
||||
// key = hostname "/" kpath |
||||
// kpath = ksegment *[ "/" ksegment ] |
||||
// ksegment = alphadigit | *[ alphadigit | "-" | "_" | "." ] |
||||
// |
||||
// where "hostname" and "alphadigit" are defined as in RFC 1738. |
||||
// |
||||
// Example key: |
||||
// spanner.google.com/universe |
||||
required string key = 1; |
||||
|
||||
// The value of the label. |
||||
oneof value { |
||||
// A string value. |
||||
string str_value = 2; |
||||
// An integer value. |
||||
int64 num_value = 3; |
||||
} |
||||
} |
||||
|
||||
// A collection of labels, such as the set of all labels attached to an |
||||
// object. Each label in the set must have a different key. |
||||
// |
||||
// Users should prefer to embed "repeated Label" directly when possible. |
||||
// This message should only be used in cases where that isn't possible (e.g. |
||||
// with oneof). |
||||
message Labels { |
||||
repeated Label label = 1; |
||||
} |
@ -0,0 +1,702 @@ |
||||
// Specification of the Pubsub API. |
||||
|
||||
syntax = "proto2"; |
||||
|
||||
import "examples/tips/empty.proto"; |
||||
import "examples/tips/label.proto"; |
||||
|
||||
package tech.pubsub; |
||||
|
||||
// ----------------------------------------------------------------------------- |
||||
// Overview of the Pubsub API |
||||
// ----------------------------------------------------------------------------- |
||||
|
||||
// This file describes an API for a Pubsub system. This system provides a |
||||
// reliable many-to-many communication mechanism between independently written |
||||
// publishers and subscribers where the publisher publishes messages to "topics" |
||||
// and each subscriber creates a "subscription" and consumes messages from it. |
||||
// |
||||
// (a) The pubsub system maintains bindings between topics and subscriptions. |
||||
// (b) A publisher publishes messages into a topic. |
||||
// (c) The pubsub system delivers messages from topics into relevant |
||||
// subscriptions. |
||||
// (d) A subscriber receives pending messages from its subscription and |
||||
// acknowledges or nacks each one to the pubsub system. |
||||
// (e) The pubsub system removes acknowledged messages from that subscription. |
||||
|
||||
// ----------------------------------------------------------------------------- |
||||
// Data Model |
||||
// ----------------------------------------------------------------------------- |
||||
|
||||
// The data model consists of the following: |
||||
// |
||||
// * Topic: A topic is a resource to which messages are published by publishers. |
||||
// Topics are named, and the name of the topic is unique within the pubsub |
||||
// system. |
||||
// |
||||
// * Subscription: A subscription records the subscriber's interest in a topic. |
||||
// It can optionally include a query to select a subset of interesting |
||||
// messages. The pubsub system maintains a logical cursor tracking the |
||||
// matching messages which still need to be delivered and acked so that |
||||
// they can retried as needed. The set of messages that have not been |
||||
// acknowledged is called the subscription backlog. |
||||
// |
||||
// * Message: A message is a unit of data that flows in the system. It contains |
||||
// opaque data from the publisher along with its labels. |
||||
// |
||||
// * Message Labels (optional): A set of opaque key, value pairs assigned |
||||
// by the publisher which the subscriber can use for filtering out messages |
||||
// in the topic. For example, a label with key "foo.com/device_type" and |
||||
// value "mobile" may be added for messages that are only relevant for a |
||||
// mobile subscriber; a subscriber on a phone may decide to create a |
||||
// subscription only for messages that have this label. |
||||
|
||||
// ----------------------------------------------------------------------------- |
||||
// Publisher Flow |
||||
// ----------------------------------------------------------------------------- |
||||
|
||||
// A publisher publishes messages to the topic using the Publish request: |
||||
// |
||||
// PubsubMessage message; |
||||
// message.set_data("...."); |
||||
// Label label; |
||||
// label.set_key("foo.com/key1"); |
||||
// label.set_str_value("value1"); |
||||
// message.add_label(label); |
||||
// PublishRequest request; |
||||
// request.set_topic("topicName"); |
||||
// request.set_message(message); |
||||
// PublisherService.Publish(request); |
||||
|
||||
// ----------------------------------------------------------------------------- |
||||
// Subscriber Flow |
||||
// ----------------------------------------------------------------------------- |
||||
|
||||
// The subscriber part of the API is richer than the publisher part and has a |
||||
// number of concepts w.r.t. subscription creation and monitoring: |
||||
// |
||||
// (1) A subscriber creates a subscription using the CreateSubscription call. |
||||
// It may specify an optional "query" to indicate that it wants to receive |
||||
// only messages with a certain set of labels using the label query syntax. |
||||
// It may also specify an optional truncation policy to indicate when old |
||||
// messages from the subcription can be removed. |
||||
// |
||||
// (2) A subscriber receives messages in one of two ways: via push or pull. |
||||
// |
||||
// (a) To receive messages via push, the PushConfig field must be specified in |
||||
// the Subscription parameter when creating a subscription. The PushConfig |
||||
// specifies an endpoint at which the subscriber must expose the |
||||
// PushEndpointService. Messages are received via the HandlePubsubEvent |
||||
// method. The push subscriber responds to the HandlePubsubEvent method |
||||
// with a result code that indicates one of three things: Ack (the message |
||||
// has been successfully processed and the Pubsub system may delete it), |
||||
// Nack (the message has been rejected, the Pubsub system should resend it |
||||
// at a later time), or Push-Back (this is a Nack with the additional |
||||
// semantics that the subscriber is overloaded and the pubsub system should |
||||
// back off on the rate at which it is invoking HandlePubsubEvent). The |
||||
// endpoint may be a load balancer for better scalability. |
||||
// |
||||
// (b) To receive messages via pull a subscriber calls the Pull method on the |
||||
// SubscriberService to get messages from the subscription. For each |
||||
// individual message, the subscriber may use the ack_id received in the |
||||
// PullResponse to Ack the message, Nack the message, or modify the ack |
||||
// deadline with ModifyAckDeadline. See the |
||||
// Subscription.ack_deadline_seconds field documentation for details on the |
||||
// ack deadline behavior. |
||||
// |
||||
// Note: Messages may be consumed in parallel by multiple subscribers making |
||||
// Pull calls to the same subscription; this will result in the set of |
||||
// messages from the subscription being shared and each subscriber |
||||
// receiving a subset of the messages. |
||||
// |
||||
// (4) The subscriber can explicitly truncate the current subscription. |
||||
// |
||||
// (5) "Truncated" events are delivered when a subscription is |
||||
// truncated, whether due to the subscription's truncation policy |
||||
// or an explicit request from the subscriber. |
||||
// |
||||
// Subscription creation: |
||||
// |
||||
// Subscription subscription; |
||||
// subscription.set_topic("topicName"); |
||||
// subscription.set_name("subscriptionName"); |
||||
// subscription.push_config().set_push_endpoint("machinename:8888"); |
||||
// SubscriberService.CreateSubscription(subscription); |
||||
// |
||||
// Consuming messages via push: |
||||
// |
||||
// TODO(eschapira): Add HTTP push example. |
||||
// |
||||
// The port 'machinename:8888' must be bound to a stubby server that implements |
||||
// the PushEndpointService with the following method: |
||||
// |
||||
// int HandlePubsubEvent(PubsubEvent event) { |
||||
// if (event.subscription().equals("subscriptionName")) { |
||||
// if (event.has_message()) { |
||||
// Process(event.message().data()); |
||||
// } else if (event.truncated()) { |
||||
// ProcessTruncatedEvent(); |
||||
// } |
||||
// } |
||||
// return OK; // This return code implies an acknowledgment |
||||
// } |
||||
// |
||||
// Consuming messages via pull: |
||||
// |
||||
// The subscription must be created without setting the push_config field. |
||||
// |
||||
// PullRequest pull_request; |
||||
// pull_request.set_subscription("subscriptionName"); |
||||
// pull_request.set_return_immediately(false); |
||||
// while (true) { |
||||
// PullResponse pull_response; |
||||
// if (SubscriberService.Pull(pull_request, pull_response) == OK) { |
||||
// PubsubEvent event = pull_response.pubsub_event(); |
||||
// if (event.has_message()) { |
||||
// Process(event.message().data()); |
||||
// } else if (event.truncated()) { |
||||
// ProcessTruncatedEvent(); |
||||
// } |
||||
// AcknowledgeRequest ack_request; |
||||
// ackRequest.set_subscription("subscriptionName"); |
||||
// ackRequest.set_ack_id(pull_response.ack_id()); |
||||
// SubscriberService.Acknowledge(ack_request); |
||||
// } |
||||
// } |
||||
|
||||
// ----------------------------------------------------------------------------- |
||||
// Reliability Semantics |
||||
// ----------------------------------------------------------------------------- |
||||
|
||||
// When a subscriber successfully creates a subscription using |
||||
// Subscriber.CreateSubscription, it establishes a "subscription point" with |
||||
// respect to that subscription - the subscriber is guaranteed to receive any |
||||
// message published after this subscription point that matches the |
||||
// subscription's query. Note that messages published before the Subscription |
||||
// point may or may not be delivered. |
||||
// |
||||
// If the system truncates the subscription according to the specified |
||||
// truncation policy, the system delivers a subscription status event with the |
||||
// "truncated" field set to true. We refer to such events as "truncation |
||||
// events". A truncation event: |
||||
// |
||||
// * Informs the subscriber that part of the subscription messages have been |
||||
// discarded. The subscriber may want to recover from the message loss, e.g., |
||||
// by resyncing its state with its backend. |
||||
// * Establishes a new subscription point, i.e., the subscriber is guaranteed to |
||||
// receive all changes published after the trunction event is received (or |
||||
// until another truncation event is received). |
||||
// |
||||
// Note that messages are not delivered in any particular order by the pubsub |
||||
// system. Furthermore, the system guarantees at-least-once delivery |
||||
// of each message or truncation events until acked. |
||||
|
||||
// ----------------------------------------------------------------------------- |
||||
// Deletion |
||||
// ----------------------------------------------------------------------------- |
||||
|
||||
// Both topics and subscriptions may be deleted. Deletion of a topic implies |
||||
// deletion of all attached subscriptions. |
||||
// |
||||
// When a subscription is deleted directly by calling DeleteSubscription, all |
||||
// messages are immediately dropped. If it is a pull subscriber, future pull |
||||
// requests will return NOT_FOUND. |
||||
// |
||||
// When a topic is deleted all corresponding subscriptions are immediately |
||||
// deleted, and subscribers experience the same behavior as directly deleting |
||||
// the subscription. |
||||
|
||||
// ----------------------------------------------------------------------------- |
||||
// The Publisher service and its protos. |
||||
// ----------------------------------------------------------------------------- |
||||
|
||||
// The service that an application uses to manipulate topics, and to send |
||||
// messages to a topic. |
||||
service PublisherService { |
||||
|
||||
// Creates the given topic with the given name. |
||||
rpc CreateTopic(Topic) returns (Topic) { |
||||
} |
||||
|
||||
// Adds a message to the topic. Returns NOT_FOUND if the topic does not |
||||
// exist. |
||||
// (-- For different error code values returned via Stubby, see |
||||
// util/task/codes.proto. --) |
||||
rpc Publish(PublishRequest) returns (proto2.Empty) { |
||||
} |
||||
|
||||
// Adds one or more messages to the topic. Returns NOT_FOUND if the topic does |
||||
// not exist. |
||||
rpc PublishBatch(PublishBatchRequest) returns (PublishBatchResponse) { |
||||
} |
||||
|
||||
// Gets the configuration of a topic. Since the topic only has the name |
||||
// attribute, this method is only useful to check the existence of a topic. |
||||
// If other attributes are added in the future, they will be returned here. |
||||
rpc GetTopic(GetTopicRequest) returns (Topic) { |
||||
} |
||||
|
||||
// Lists matching topics. |
||||
rpc ListTopics(ListTopicsRequest) returns (ListTopicsResponse) { |
||||
} |
||||
|
||||
// Deletes the topic with the given name. All subscriptions to this topic |
||||
// are also deleted. Returns NOT_FOUND if the topic does not exist. |
||||
// After a topic is deleted, a new topic may be created with the same name. |
||||
rpc DeleteTopic(DeleteTopicRequest) returns (proto2.Empty) { |
||||
} |
||||
} |
||||
|
||||
// A topic resource. |
||||
message Topic { |
||||
// Name of the topic. |
||||
optional string name = 1; |
||||
} |
||||
|
||||
// A message data and its labels. |
||||
message PubsubMessage { |
||||
// The message payload. |
||||
optional bytes data = 1; |
||||
|
||||
// Optional list of labels for this message. Keys in this collection must |
||||
// be unique. |
||||
//(-- TODO(eschapira): Define how key namespace may be scoped to the topic.--) |
||||
repeated tech.label.Label label = 2; |
||||
|
||||
// ID of this message assigned by the server at publication time. Guaranteed |
||||
// to be unique within the topic. This value may be read by a subscriber |
||||
// that receives a PubsubMessage via a Pull call or a push delivery. It must |
||||
// not be populated by a publisher in a Publish call. |
||||
optional string message_id = 3; |
||||
} |
||||
|
||||
// Request for the GetTopic method. |
||||
message GetTopicRequest { |
||||
// The name of the topic to get. |
||||
optional string topic = 1; |
||||
} |
||||
|
||||
// Request for the Publish method. |
||||
message PublishRequest { |
||||
// The message in the request will be published on this topic. |
||||
optional string topic = 1; |
||||
|
||||
// The message to publish. |
||||
optional PubsubMessage message = 2; |
||||
} |
||||
|
||||
// Request for the PublishBatch method. |
||||
message PublishBatchRequest { |
||||
// The messages in the request will be published on this topic. |
||||
optional string topic = 1; |
||||
|
||||
// The messages to publish. |
||||
repeated PubsubMessage messages = 2; |
||||
} |
||||
|
||||
// Response for the PublishBatch method. |
||||
message PublishBatchResponse { |
||||
// The server-assigned ID of each published message, in the same order as |
||||
// the messages in the request. IDs are guaranteed to be unique within |
||||
// the topic. |
||||
repeated string message_ids = 1; |
||||
} |
||||
|
||||
// Request for the ListTopics method. |
||||
message ListTopicsRequest { |
||||
// A valid label query expression. |
||||
// (-- Which labels are required or supported is implementation-specific. --) |
||||
optional string query = 1; |
||||
|
||||
// Maximum number of topics to return. |
||||
// (-- If not specified or <= 0, the implementation will select a reasonable |
||||
// value. --) |
||||
optional int32 max_results = 2; |
||||
|
||||
// The value obtained in the last <code>ListTopicsResponse</code> |
||||
// for continuation. |
||||
optional string page_token = 3; |
||||
|
||||
} |
||||
|
||||
// Response for the ListTopics method. |
||||
message ListTopicsResponse { |
||||
// The resulting topics. |
||||
repeated Topic topic = 1; |
||||
|
||||
// If not empty, indicates that there are more topics that match the request, |
||||
// and this value should be passed to the next <code>ListTopicsRequest</code> |
||||
// to continue. |
||||
optional string next_page_token = 2; |
||||
} |
||||
|
||||
// Request for the Delete method. |
||||
message DeleteTopicRequest { |
||||
// Name of the topic to delete. |
||||
optional string topic = 1; |
||||
} |
||||
|
||||
// ----------------------------------------------------------------------------- |
||||
// The Subscriber service and its protos. |
||||
// ----------------------------------------------------------------------------- |
||||
|
||||
// The service that an application uses to manipulate subscriptions and to |
||||
// consume messages from a subscription via the pull method. |
||||
service SubscriberService { |
||||
|
||||
// Creates a subscription on a given topic for a given subscriber. |
||||
// If the subscription already exists, returns ALREADY_EXISTS. |
||||
// If the corresponding topic doesn't exist, returns NOT_FOUND. |
||||
// |
||||
// If the name is not provided in the request, the server will assign a random |
||||
// name for this subscription on the same project as the topic. |
||||
rpc CreateSubscription(Subscription) returns (Subscription) { |
||||
} |
||||
|
||||
// Gets the configuration details of a subscription. |
||||
rpc GetSubscription(GetSubscriptionRequest) returns (Subscription) { |
||||
} |
||||
|
||||
// Lists matching subscriptions. |
||||
rpc ListSubscriptions(ListSubscriptionsRequest) |
||||
returns (ListSubscriptionsResponse) { |
||||
} |
||||
|
||||
// Deletes an existing subscription. All pending messages in the subscription |
||||
// are immediately dropped. Calls to Pull after deletion will return |
||||
// NOT_FOUND. |
||||
rpc DeleteSubscription(DeleteSubscriptionRequest) returns (proto2.Empty) { |
||||
} |
||||
|
||||
// Removes all the pending messages in the subscription and releases the |
||||
// storage associated with them. Results in a truncation event to be sent to |
||||
// the subscriber. Messages added after this call returns are stored in the |
||||
// subscription as before. |
||||
rpc TruncateSubscription(TruncateSubscriptionRequest) returns (proto2.Empty) { |
||||
} |
||||
|
||||
// |
||||
// Push subscriber calls. |
||||
// |
||||
|
||||
// Modifies the <code>PushConfig</code> for a specified subscription. |
||||
// This method can be used to suspend the flow of messages to an endpoint |
||||
// by clearing the <code>PushConfig</code> field in the request. Messages |
||||
// will be accumulated for delivery even if no push configuration is |
||||
// defined or while the configuration is modified. |
||||
rpc ModifyPushConfig(ModifyPushConfigRequest) returns (proto2.Empty) { |
||||
} |
||||
|
||||
// |
||||
// Pull Subscriber calls |
||||
// |
||||
|
||||
// Pulls a single message from the server. |
||||
// If return_immediately is true, and no messages are available in the |
||||
// subscription, this method returns FAILED_PRECONDITION. The system is free |
||||
// to return an UNAVAILABLE error if no messages are available in a |
||||
// reasonable amount of time (to reduce system load). |
||||
rpc Pull(PullRequest) returns (PullResponse) { |
||||
} |
||||
|
||||
// Pulls messages from the server. Returns an empty list if there are no |
||||
// messages available in the backlog. The system is free to return UNAVAILABLE |
||||
// if there are too many pull requests outstanding for the given subscription. |
||||
rpc PullBatch(PullBatchRequest) returns (PullBatchResponse) { |
||||
} |
||||
|
||||
// Modifies the Ack deadline for a message received from a pull request. |
||||
rpc ModifyAckDeadline(ModifyAckDeadlineRequest) returns (proto2.Empty) { |
||||
} |
||||
|
||||
// Acknowledges a particular received message: the Pub/Sub system can remove |
||||
// the given message from the subscription. Acknowledging a message whose |
||||
// Ack deadline has expired may succeed, but the message could have been |
||||
// already redelivered. Acknowledging a message more than once will not |
||||
// result in an error. This is only used for messages received via pull. |
||||
rpc Acknowledge(AcknowledgeRequest) returns (proto2.Empty) { |
||||
} |
||||
|
||||
// Refuses processing a particular received message. The system will |
||||
// redeliver this message to some consumer of the subscription at some |
||||
// future time. This is only used for messages received via pull. |
||||
rpc Nack(NackRequest) returns (proto2.Empty) { |
||||
} |
||||
} |
||||
|
||||
// A subscription resource. |
||||
message Subscription { |
||||
// Name of the subscription. |
||||
optional string name = 1; |
||||
|
||||
// The name of the topic from which this subscription is receiving messages. |
||||
optional string topic = 2; |
||||
|
||||
// If <code>query</code> is non-empty, only messages on the subscriber's |
||||
// topic whose labels match the query will be returned. Otherwise all |
||||
// messages on the topic will be returned. |
||||
// (-- The query syntax is described in tech/label/proto/label_query.proto --) |
||||
optional string query = 3; |
||||
|
||||
// The subscriber may specify requirements for truncating unacknowledged |
||||
// subscription entries. The system will honor the |
||||
// <code>CreateSubscription</code> request only if it can meet these |
||||
// requirements. If this field is not specified, messages are never truncated |
||||
// by the system. |
||||
optional TruncationPolicy truncation_policy = 4; |
||||
|
||||
// Specifies which messages can be truncated by the system. |
||||
message TruncationPolicy { |
||||
oneof policy { |
||||
// If <code>max_bytes</code> is specified, the system is allowed to drop |
||||
// old messages to keep the combined size of stored messages under |
||||
// <code>max_bytes</code>. This is a hint; the system may keep more than |
||||
// this many bytes, but will make a best effort to keep the size from |
||||
// growing much beyond this parameter. |
||||
int64 max_bytes = 1; |
||||
|
||||
// If <code>max_age_seconds</code> is specified, the system is allowed to |
||||
// drop messages that have been stored for at least this many seconds. |
||||
// This is a hint; the system may keep these messages, but will make a |
||||
// best effort to remove them when their maximum age is reached. |
||||
int64 max_age_seconds = 2; |
||||
} |
||||
} |
||||
|
||||
// If push delivery is used with this subscription, this field is |
||||
// used to configure it. |
||||
optional PushConfig push_config = 5; |
||||
|
||||
// For either push or pull delivery, the value is the maximum time after a |
||||
// subscriber receives a message before the subscriber should acknowledge or |
||||
// Nack the message. If the Ack deadline for a message passes without an |
||||
// Ack or a Nack, the Pub/Sub system will eventually redeliver the message. |
||||
// If a subscriber acknowledges after the deadline, the Pub/Sub system may |
||||
// accept the Ack, but it is possible that the message has been already |
||||
// delivered again. Multiple Acks to the message are allowed and will |
||||
// succeed. |
||||
// |
||||
// For push delivery, this value is used to set the request timeout for |
||||
// the call to the push endpoint. |
||||
// |
||||
// For pull delivery, this value is used as the initial value for the Ack |
||||
// deadline. It may be overridden for a specific pull request (message) with |
||||
// <code>ModifyAckDeadline</code>. |
||||
// While a message is outstanding (i.e. it has been delivered to a pull |
||||
// subscriber and the subscriber has not yet Acked or Nacked), the Pub/Sub |
||||
// system will not deliver that message to another pull subscriber |
||||
// (on a best-effort basis). |
||||
optional int32 ack_deadline_seconds = 6; |
||||
|
||||
// If this parameter is set to n, the system is allowed to (but not required |
||||
// to) delete the subscription when at least n seconds have elapsed since the |
||||
// client presence was detected. (Presence is detected through any |
||||
// interaction using the subscription ID, including Pull(), Get(), or |
||||
// acknowledging a message.) |
||||
// |
||||
// If this parameter is not set, the subscription will stay live until |
||||
// explicitly deleted. |
||||
// |
||||
// Clients can detect such garbage collection when a Get call or a Pull call |
||||
// (for pull subscribers only) returns NOT_FOUND. |
||||
optional int64 garbage_collect_seconds = 7; |
||||
} |
||||
|
||||
// Configuration for a push delivery endpoint. |
||||
message PushConfig { |
||||
// A URL locating the endpoint to which messages should be pushed. |
||||
// For example, a Webhook endpoint might use "https://example.com/push". |
||||
// (-- An Android application might use "gcm:<REGID>", where <REGID> is a |
||||
// GCM registration id allocated for pushing messages to the application. --) |
||||
optional string push_endpoint = 1; |
||||
} |
||||
|
||||
// An event indicating a received message or truncation event. |
||||
message PubsubEvent { |
||||
// The subscription that received the event. |
||||
optional string subscription = 1; |
||||
|
||||
oneof type { |
||||
// A received message. |
||||
PubsubMessage message = 2; |
||||
|
||||
// Indicates that this subscription has been truncated. |
||||
bool truncated = 3; |
||||
|
||||
// Indicates that this subscription has been deleted. (Note that pull |
||||
// subscribers will always receive NOT_FOUND in response in their pull |
||||
// request on the subscription, rather than seeing this boolean.) |
||||
bool deleted = 4; |
||||
} |
||||
} |
||||
|
||||
// Request for the GetSubscription method. |
||||
message GetSubscriptionRequest { |
||||
// The name of the subscription to get. |
||||
optional string subscription = 1; |
||||
} |
||||
|
||||
// Request for the ListSubscriptions method. |
||||
message ListSubscriptionsRequest { |
||||
// A valid label query expression. |
||||
// (-- Which labels are required or supported is implementation-specific. |
||||
// TODO(eschapira): This method must support to query by topic. We must |
||||
// define the key URI for the "topic" label. --) |
||||
optional string query = 1; |
||||
|
||||
// Maximum number of subscriptions to return. |
||||
// (-- If not specified or <= 0, the implementation will select a reasonable |
||||
// value. --) |
||||
optional int32 max_results = 3; |
||||
|
||||
// The value obtained in the last <code>ListSubscriptionsResponse</code> |
||||
// for continuation. |
||||
optional string page_token = 4; |
||||
} |
||||
|
||||
// Response for the ListSubscriptions method. |
||||
message ListSubscriptionsResponse { |
||||
// The subscriptions that match the request. |
||||
repeated Subscription subscription = 1; |
||||
|
||||
// If not empty, indicates that there are more subscriptions that match the |
||||
// request and this value should be passed to the next |
||||
// <code>ListSubscriptionsRequest</code> to continue. |
||||
optional string next_page_token = 2; |
||||
} |
||||
|
||||
// Request for the TruncateSubscription method. |
||||
message TruncateSubscriptionRequest { |
||||
// The subscription that is being truncated. |
||||
optional string subscription = 1; |
||||
} |
||||
|
||||
// Request for the DeleteSubscription method. |
||||
message DeleteSubscriptionRequest { |
||||
// The subscription to delete. |
||||
optional string subscription = 1; |
||||
} |
||||
|
||||
// Request for the ModifyPushConfig method. |
||||
message ModifyPushConfigRequest { |
||||
// The name of the subscription. |
||||
optional string subscription = 1; |
||||
|
||||
// An empty <code>push_config</code> indicates that the Pub/Sub system should |
||||
// pause pushing messages from the given subscription. |
||||
optional PushConfig push_config = 2; |
||||
} |
||||
|
||||
// ----------------------------------------------------------------------------- |
||||
// The protos used by a pull subscriber. |
||||
// ----------------------------------------------------------------------------- |
||||
|
||||
// Request for the Pull method. |
||||
message PullRequest { |
||||
// The subscription from which a message should be pulled. |
||||
optional string subscription = 1; |
||||
|
||||
// If this is specified as true the system will respond immediately even if |
||||
// it is not able to return a message in the Pull response. Otherwise the |
||||
// system is allowed to wait until at least one message is available rather |
||||
// than returning FAILED_PRECONDITION. The client may cancel the request if |
||||
// it does not wish to wait any longer for the response. |
||||
optional bool return_immediately = 2; |
||||
} |
||||
|
||||
// Either a <code>PubsubMessage</code> or a truncation event. One of these two |
||||
// must be populated. |
||||
message PullResponse { |
||||
// This ID must be used to acknowledge the received event or message. |
||||
optional string ack_id = 1; |
||||
|
||||
// A pubsub message or truncation event. |
||||
optional PubsubEvent pubsub_event = 2; |
||||
} |
||||
|
||||
// Request for the PullBatch method. |
||||
message PullBatchRequest { |
||||
// The subscription from which messages should be pulled. |
||||
optional string subscription = 1; |
||||
|
||||
// If this is specified as true the system will respond immediately even if |
||||
// it is not able to return a message in the Pull response. Otherwise the |
||||
// system is allowed to wait until at least one message is available rather |
||||
// than returning no messages. The client may cancel the request if it does |
||||
// not wish to wait any longer for the response. |
||||
optional bool return_immediately = 2; |
||||
|
||||
// The maximum number of PubsubEvents returned for this request. The Pub/Sub |
||||
// system may return fewer than the number of events specified. |
||||
optional int32 max_events = 3; |
||||
} |
||||
|
||||
// Response for the PullBatch method. |
||||
message PullBatchResponse { |
||||
|
||||
// Received Pub/Sub messages or status events. The Pub/Sub system will return |
||||
// zero messages if there are no more messages available in the backlog. The |
||||
// Pub/Sub system may return fewer than the max_events requested even if |
||||
// there are more messages available in the backlog. |
||||
repeated PullResponse pull_responses = 2; |
||||
} |
||||
|
||||
// Request for the ModifyAckDeadline method. |
||||
message ModifyAckDeadlineRequest { |
||||
// The name of the subscription from which messages are being pulled. |
||||
optional string subscription = 1; |
||||
|
||||
// The acknowledgment ID. |
||||
optional string ack_id = 2; |
||||
|
||||
// The new Ack deadline. Must be >= 0. |
||||
optional int32 ack_deadline_seconds = 3; |
||||
} |
||||
|
||||
// Request for the Acknowledge method. |
||||
message AcknowledgeRequest { |
||||
// The subscription whose message is being acknowledged. |
||||
optional string subscription = 1; |
||||
|
||||
// The acknowledgment ID for the message being acknowledged. This was |
||||
// returned by the Pub/Sub system in the Pull response. |
||||
repeated string ack_id = 2; |
||||
} |
||||
|
||||
// Request for the Nack method. |
||||
message NackRequest { |
||||
// The subscription whose message is being Nacked. |
||||
optional string subscription = 1; |
||||
|
||||
// The acknowledgment ID for the message being refused. This was returned by |
||||
// the Pub/Sub system in the Pull response. |
||||
repeated string ack_id = 2; |
||||
} |
||||
|
||||
// ----------------------------------------------------------------------------- |
||||
// The service and protos used by a push subscriber. |
||||
// ----------------------------------------------------------------------------- |
||||
|
||||
// The service that a subscriber uses to handle messages sent via push |
||||
// delivery. |
||||
// This service is not currently exported for HTTP clients. |
||||
// TODO(eschapira): Explain HTTP subscribers. |
||||
service PushEndpointService { |
||||
// Sends a <code>PubsubMessage</code> or a subscription status event to a |
||||
// push endpoint. |
||||
// The push endpoint responds with an empty message and a code from |
||||
// util/task/codes.proto. The following codes have a particular meaning to the |
||||
// Pub/Sub system: |
||||
// OK - This is interpreted by Pub/Sub as Ack. |
||||
// ABORTED - This is intepreted by Pub/Sub as a Nack, without implying |
||||
// pushback for congestion control. The Pub/Sub system will |
||||
// retry this message at a later time. |
||||
// UNAVAILABLE - This is intepreted by Pub/Sub as a Nack, with the additional |
||||
// semantics of push-back. The Pub/Sub system will use an AIMD |
||||
// congestion control algorithm to backoff the rate of sending |
||||
// messages from this subscription. |
||||
// Any other code, or a failure to respond, will be interpreted in the same |
||||
// way as ABORTED; i.e. the system will retry the message at a later time to |
||||
// ensure reliable delivery. |
||||
rpc HandlePubsubEvent(PubsubEvent) returns (proto2.Empty); |
||||
} |
@ -0,0 +1,45 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef __GRPC_INTERNAL_IOMGR_POLLSET_KICK_WINDOWS_H_ |
||||
#define __GRPC_INTERNAL_IOMGR_POLLSET_KICK_WINDOWS_H_ |
||||
|
||||
#include <grpc/support/sync.h> |
||||
|
||||
struct grpc_kick_pipe_info; |
||||
|
||||
typedef struct grpc_pollset_kick_state { |
||||
int unused; |
||||
} grpc_pollset_kick_state; |
||||
|
||||
#endif /* __GRPC_INTERNAL_IOMGR_POLLSET_KICK_WINDOWS_H_ */ |
@ -0,0 +1,38 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GPR_WIN32 |
||||
|
||||
#endif /* GPR_WIN32 */ |
@ -0,0 +1,54 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef __GRPC_INTERNAL_IOMGR_POLLSET_WINDOWS_H_ |
||||
#define __GRPC_INTERNAL_IOMGR_POLLSET_WINDOWS_H_ |
||||
|
||||
#include <grpc/support/sync.h> |
||||
|
||||
#include "src/core/iomgr/pollset_kick.h" |
||||
|
||||
/* forward declare only in this file to avoid leaking impl details via
|
||||
pollset.h; real users of grpc_fd should always include 'fd_posix.h' and not |
||||
use the struct tag */ |
||||
struct grpc_fd; |
||||
|
||||
typedef struct grpc_pollset { |
||||
gpr_mu mu; |
||||
gpr_cv cv; |
||||
} grpc_pollset; |
||||
|
||||
#define GRPC_POLLSET_MU(pollset) (&(pollset)->mu) |
||||
#define GRPC_POLLSET_CV(pollset) (&(pollset)->cv) |
||||
|
||||
#endif /* __GRPC_INTERNAL_IOMGR_POLLSET_WINDOWS_H_ */ |
@ -0,0 +1,19 @@ |
||||
syntax = "proto2"; |
||||
|
||||
package grpc.testing; |
||||
|
||||
// An empty message that you can re-use to avoid defining duplicated empty |
||||
// messages in your project. A typical example is to use it as argument or the |
||||
// return value of a service API. For instance: |
||||
// |
||||
// service Foo { |
||||
// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { }; |
||||
// }; |
||||
// |
||||
// MOE:begin_strip |
||||
// The difference between this one and net/rpc/empty-message.proto is that |
||||
// 1) The generated message here is in proto2 C++ API. |
||||
// 2) The proto2.Empty has minimum dependencies |
||||
// (no message_set or net/rpc dependencies) |
||||
// MOE:end_strip |
||||
message Empty {} |
@ -0,0 +1,274 @@ |
||||
/* |
||||
* |
||||
* Copyright 2014, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
var fs = require('fs'); |
||||
var path = require('path'); |
||||
var grpc = require('..'); |
||||
var testProto = grpc.load(__dirname + '/test.proto').grpc.testing; |
||||
|
||||
var assert = require('assert'); |
||||
|
||||
/** |
||||
* Create a buffer filled with size zeroes |
||||
* @param {number} size The length of the buffer |
||||
* @return {Buffer} The new buffer |
||||
*/ |
||||
function zeroBuffer(size) { |
||||
var zeros = new Buffer(size); |
||||
zeros.fill(0); |
||||
return zeros; |
||||
} |
||||
|
||||
/** |
||||
* Run the empty_unary test |
||||
* @param {Client} client The client to test against |
||||
* @param {function} done Callback to call when the test is completed. Included |
||||
* primarily for use with mocha |
||||
*/ |
||||
function emptyUnary(client, done) { |
||||
var call = client.emptyCall({}, function(err, resp) { |
||||
assert.ifError(err); |
||||
}); |
||||
call.on('status', function(status) { |
||||
assert.strictEqual(status.code, grpc.status.OK); |
||||
if (done) { |
||||
done(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Run the large_unary test |
||||
* @param {Client} client The client to test against |
||||
* @param {function} done Callback to call when the test is completed. Included |
||||
* primarily for use with mocha |
||||
*/ |
||||
function largeUnary(client, done) { |
||||
var arg = { |
||||
response_type: testProto.PayloadType.COMPRESSABLE, |
||||
response_size: 314159, |
||||
payload: { |
||||
body: zeroBuffer(271828) |
||||
} |
||||
}; |
||||
var call = client.unaryCall(arg, function(err, resp) { |
||||
assert.ifError(err); |
||||
assert.strictEqual(resp.payload.type, testProto.PayloadType.COMPRESSABLE); |
||||
assert.strictEqual(resp.payload.body.limit - resp.payload.body.offset, |
||||
314159); |
||||
}); |
||||
call.on('status', function(status) { |
||||
assert.strictEqual(status.code, grpc.status.OK); |
||||
if (done) { |
||||
done(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Run the client_streaming test |
||||
* @param {Client} client The client to test against |
||||
* @param {function} done Callback to call when the test is completed. Included |
||||
* primarily for use with mocha |
||||
*/ |
||||
function clientStreaming(client, done) { |
||||
var call = client.streamingInputCall(function(err, resp) { |
||||
assert.ifError(err); |
||||
assert.strictEqual(resp.aggregated_payload_size, 74922); |
||||
}); |
||||
call.on('status', function(status) { |
||||
assert.strictEqual(status.code, grpc.status.OK); |
||||
if (done) { |
||||
done(); |
||||
} |
||||
}); |
||||
var payload_sizes = [27182, 8, 1828, 45904]; |
||||
for (var i = 0; i < payload_sizes.length; i++) { |
||||
call.write({payload: {body: zeroBuffer(payload_sizes[i])}}); |
||||
} |
||||
call.end(); |
||||
} |
||||
|
||||
/** |
||||
* Run the server_streaming test |
||||
* @param {Client} client The client to test against |
||||
* @param {function} done Callback to call when the test is completed. Included |
||||
* primarily for use with mocha |
||||
*/ |
||||
function serverStreaming(client, done) { |
||||
var arg = { |
||||
response_type: testProto.PayloadType.COMPRESSABLE, |
||||
response_parameters: [ |
||||
{size: 31415}, |
||||
{size: 9}, |
||||
{size: 2653}, |
||||
{size: 58979} |
||||
] |
||||
}; |
||||
var call = client.streamingOutputCall(arg); |
||||
var resp_index = 0; |
||||
call.on('data', function(value) { |
||||
assert(resp_index < 4); |
||||
assert.strictEqual(value.payload.type, testProto.PayloadType.COMPRESSABLE); |
||||
assert.strictEqual(value.payload.body.limit - value.payload.body.offset, |
||||
arg.response_parameters[resp_index].size); |
||||
resp_index += 1; |
||||
}); |
||||
call.on('status', function(status) { |
||||
assert.strictEqual(resp_index, 4); |
||||
assert.strictEqual(status.code, grpc.status.OK); |
||||
if (done) { |
||||
done(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Run the ping_pong test |
||||
* @param {Client} client The client to test against |
||||
* @param {function} done Callback to call when the test is completed. Included |
||||
* primarily for use with mocha |
||||
*/ |
||||
function pingPong(client, done) { |
||||
var payload_sizes = [27182, 8, 1828, 45904]; |
||||
var response_sizes = [31415, 9, 2653, 58979]; |
||||
var call = client.fullDuplexCall(); |
||||
call.on('status', function(status) { |
||||
assert.strictEqual(status.code, grpc.status.OK); |
||||
if (done) { |
||||
done(); |
||||
} |
||||
}); |
||||
var index = 0; |
||||
call.write({ |
||||
response_type: testProto.PayloadType.COMPRESSABLE, |
||||
response_parameters: [ |
||||
{size: response_sizes[index]} |
||||
], |
||||
payload: {body: zeroBuffer(payload_sizes[index])} |
||||
}); |
||||
call.on('data', function(response) { |
||||
assert.strictEqual(response.payload.type, |
||||
testProto.PayloadType.COMPRESSABLE); |
||||
assert.equal(response.payload.body.limit - response.payload.body.offset, |
||||
response_sizes[index]); |
||||
index += 1; |
||||
if (index == 4) { |
||||
call.end(); |
||||
} else { |
||||
call.write({ |
||||
response_type: testProto.PayloadType.COMPRESSABLE, |
||||
response_parameters: [ |
||||
{size: response_sizes[index]} |
||||
], |
||||
payload: {body: zeroBuffer(payload_sizes[index])} |
||||
}); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Run the empty_stream test. |
||||
* NOTE: This does not work, but should with the new invoke API |
||||
* @param {Client} client The client to test against |
||||
* @param {function} done Callback to call when the test is completed. Included |
||||
* primarily for use with mocha |
||||
*/ |
||||
function emptyStream(client, done) { |
||||
var call = client.fullDuplexCall(); |
||||
call.on('status', function(status) { |
||||
assert.strictEqual(status.code, grpc.status.OK); |
||||
if (done) { |
||||
done(); |
||||
} |
||||
}); |
||||
call.on('data', function(value) { |
||||
assert.fail(value, null, 'No data should have been received', '!=='); |
||||
}); |
||||
call.end(); |
||||
} |
||||
|
||||
/** |
||||
* Map from test case names to test functions |
||||
*/ |
||||
var test_cases = { |
||||
empty_unary: emptyUnary, |
||||
large_unary: largeUnary, |
||||
client_streaming: clientStreaming, |
||||
server_streaming: serverStreaming, |
||||
ping_pong: pingPong, |
||||
empty_stream: emptyStream |
||||
}; |
||||
|
||||
/** |
||||
* Execute a single test case. |
||||
* @param {string} address The address of the server to connect to, in the |
||||
* format "hostname:port" |
||||
* @param {string} host_overrirde The hostname of the server to use as an SSL |
||||
* override |
||||
* @param {string} test_case The name of the test case to run |
||||
* @param {bool} tls Indicates that a secure channel should be used |
||||
* @param {function} done Callback to call when the test is completed. Included |
||||
* primarily for use with mocha |
||||
*/ |
||||
function runTest(address, host_override, test_case, tls, done) { |
||||
// TODO(mlumish): enable TLS functionality
|
||||
var options = {}; |
||||
if (tls) { |
||||
var ca_path = path.join(__dirname, '../test/data/ca.pem'); |
||||
var ca_data = fs.readFileSync(ca_path); |
||||
var creds = grpc.Credentials.createSsl(ca_data); |
||||
options.credentials = creds; |
||||
if (host_override) { |
||||
options['grpc.ssl_target_name_override'] = host_override; |
||||
} |
||||
} |
||||
var client = new testProto.TestService(address, options); |
||||
|
||||
test_cases[test_case](client, done); |
||||
} |
||||
|
||||
if (require.main === module) { |
||||
var parseArgs = require('minimist'); |
||||
var argv = parseArgs(process.argv, { |
||||
string: ['server_host', 'server_host_override', 'server_port', 'test_case', |
||||
'use_tls', 'use_test_ca'] |
||||
}); |
||||
runTest(argv.server_host + ':' + argv.server_port, argv.server_host_override, |
||||
argv.test_case, argv.use_tls === 'true'); |
||||
} |
||||
|
||||
/** |
||||
* See docs for runTest |
||||
*/ |
||||
exports.runTest = runTest; |
@ -0,0 +1,203 @@ |
||||
/* |
||||
* |
||||
* Copyright 2014, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
var fs = require('fs'); |
||||
var path = require('path'); |
||||
var _ = require('underscore'); |
||||
var grpc = require('..'); |
||||
var testProto = grpc.load(__dirname + '/test.proto').grpc.testing; |
||||
var Server = grpc.buildServer([testProto.TestService.service]); |
||||
|
||||
/** |
||||
* Create a buffer filled with size zeroes |
||||
* @param {number} size The length of the buffer |
||||
* @return {Buffer} The new buffer |
||||
*/ |
||||
function zeroBuffer(size) { |
||||
var zeros = new Buffer(size); |
||||
zeros.fill(0); |
||||
return zeros; |
||||
} |
||||
|
||||
/** |
||||
* Respond to an empty parameter with an empty response. |
||||
* NOTE: this currently does not work due to issue #137 |
||||
* @param {Call} call Call to handle |
||||
* @param {function(Error, Object)} callback Callback to call with result |
||||
* or error |
||||
*/ |
||||
function handleEmpty(call, callback) { |
||||
callback(null, {}); |
||||
} |
||||
|
||||
/** |
||||
* Handle a unary request by sending the requested payload |
||||
* @param {Call} call Call to handle |
||||
* @param {function(Error, Object)} callback Callback to call with result or |
||||
* error |
||||
*/ |
||||
function handleUnary(call, callback) { |
||||
var req = call.request; |
||||
var zeros = zeroBuffer(req.response_size); |
||||
var payload_type = req.response_type; |
||||
if (payload_type === testProto.PayloadType.RANDOM) { |
||||
payload_type = [ |
||||
testProto.PayloadType.COMPRESSABLE, |
||||
testProto.PayloadType.UNCOMPRESSABLE][Math.random() < 0.5 ? 0 : 1]; |
||||
} |
||||
callback(null, {payload: {type: payload_type, body: zeros}}); |
||||
} |
||||
|
||||
/** |
||||
* Respond to a streaming call with the total size of all payloads |
||||
* @param {Call} call Call to handle |
||||
* @param {function(Error, Object)} callback Callback to call with result or |
||||
* error |
||||
*/ |
||||
function handleStreamingInput(call, callback) { |
||||
var aggregate_size = 0; |
||||
call.on('data', function(value) { |
||||
aggregate_size += value.payload.body.limit - value.payload.body.offset; |
||||
}); |
||||
call.on('end', function() { |
||||
callback(null, {aggregated_payload_size: aggregate_size}); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Respond to a payload request with a stream of the requested payloads |
||||
* @param {Call} call Call to handle |
||||
*/ |
||||
function handleStreamingOutput(call) { |
||||
var req = call.request; |
||||
var payload_type = req.response_type; |
||||
if (payload_type === testProto.PayloadType.RANDOM) { |
||||
payload_type = [ |
||||
testProto.PayloadType.COMPRESSABLE, |
||||
testProto.PayloadType.UNCOMPRESSABLE][Math.random() < 0.5 ? 0 : 1]; |
||||
} |
||||
_.each(req.response_parameters, function(resp_param) { |
||||
call.write({ |
||||
payload: { |
||||
body: zeroBuffer(resp_param.size), |
||||
type: payload_type |
||||
} |
||||
}); |
||||
}); |
||||
call.end(); |
||||
} |
||||
|
||||
/** |
||||
* Respond to a stream of payload requests with a stream of payload responses as |
||||
* they arrive. |
||||
* @param {Call} call Call to handle |
||||
*/ |
||||
function handleFullDuplex(call) { |
||||
call.on('data', function(value) { |
||||
var payload_type = value.response_type; |
||||
if (payload_type === testProto.PayloadType.RANDOM) { |
||||
payload_type = [ |
||||
testProto.PayloadType.COMPRESSABLE, |
||||
testProto.PayloadType.UNCOMPRESSABLE][Math.random() < 0.5 ? 0 : 1]; |
||||
} |
||||
_.each(value.response_parameters, function(resp_param) { |
||||
call.write({ |
||||
payload: { |
||||
body: zeroBuffer(resp_param.size), |
||||
type: payload_type |
||||
} |
||||
}); |
||||
}); |
||||
}); |
||||
call.on('end', function() { |
||||
call.end(); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Respond to a stream of payload requests with a stream of payload responses |
||||
* after all requests have arrived |
||||
* @param {Call} call Call to handle |
||||
*/ |
||||
function handleHalfDuplex(call) { |
||||
throw new Error('HalfDuplexCall not yet implemented'); |
||||
} |
||||
|
||||
/** |
||||
* Get a server object bound to the given port |
||||
* @param {string} port Port to which to bind |
||||
* @param {boolean} tls Indicates that the bound port should use TLS |
||||
* @return {{server: Server, port: number}} Server object bound to the support, |
||||
* and port number that the server is bound to |
||||
*/ |
||||
function getServer(port, tls) { |
||||
// TODO(mlumish): enable TLS functionality
|
||||
var options = {}; |
||||
if (tls) { |
||||
var key_path = path.join(__dirname, '../test/data/server1.key'); |
||||
var pem_path = path.join(__dirname, '../test/data/server1.pem'); |
||||
|
||||
var key_data = fs.readFileSync(key_path); |
||||
var pem_data = fs.readFileSync(pem_path); |
||||
var server_creds = grpc.ServerCredentials.createSsl(null, |
||||
key_data, |
||||
pem_data); |
||||
options.credentials = server_creds; |
||||
} |
||||
var server = new Server({ |
||||
'grpc.testing.TestService' : { |
||||
emptyCall: handleEmpty, |
||||
unaryCall: handleUnary, |
||||
streamingOutputCall: handleStreamingOutput, |
||||
streamingInputCall: handleStreamingInput, |
||||
fullDuplexCall: handleFullDuplex, |
||||
halfDuplexCall: handleHalfDuplex |
||||
} |
||||
}, options); |
||||
var port_num = server.bind('0.0.0.0:' + port, tls); |
||||
return {server: server, port: port_num}; |
||||
} |
||||
|
||||
if (require.main === module) { |
||||
var parseArgs = require('minimist'); |
||||
var argv = parseArgs(process.argv, { |
||||
string: ['port', 'use_tls'] |
||||
}); |
||||
var server_obj = getServer(argv.port, argv.use_tls === 'true'); |
||||
server_obj.server.start(); |
||||
} |
||||
|
||||
/** |
||||
* See docs for getServer |
||||
*/ |
||||
exports.getServer = getServer; |
@ -0,0 +1,94 @@ |
||||
// Message definitions to be used by integration test service definitions. |
||||
|
||||
syntax = "proto2"; |
||||
|
||||
package grpc.testing; |
||||
|
||||
// The type of payload that should be returned. |
||||
enum PayloadType { |
||||
// Compressable text format. |
||||
COMPRESSABLE = 0; |
||||
|
||||
// Uncompressable binary format. |
||||
UNCOMPRESSABLE = 1; |
||||
|
||||
// Randomly chosen from all other formats defined in this enum. |
||||
RANDOM = 2; |
||||
} |
||||
|
||||
// A block of data, to simply increase gRPC message size. |
||||
message Payload { |
||||
// The type of data in body. |
||||
optional PayloadType type = 1; |
||||
// Primary contents of payload. |
||||
optional bytes body = 2; |
||||
} |
||||
|
||||
// Unary request. |
||||
message SimpleRequest { |
||||
// Desired payload type in the response from the server. |
||||
// If response_type is RANDOM, server randomly chooses one from other formats. |
||||
optional PayloadType response_type = 1; |
||||
|
||||
// Desired payload size in the response from the server. |
||||
// If response_type is COMPRESSABLE, this denotes the size before compression. |
||||
optional int32 response_size = 2; |
||||
|
||||
// Optional input payload sent along with the request. |
||||
optional Payload payload = 3; |
||||
} |
||||
|
||||
// Unary response, as configured by the request. |
||||
message SimpleResponse { |
||||
// Payload to increase message size. |
||||
optional Payload payload = 1; |
||||
// The user the request came from, for verifying authentication was |
||||
// successful when the client expected it. |
||||
optional int64 effective_gaia_user_id = 2; |
||||
} |
||||
|
||||
// Client-streaming request. |
||||
message StreamingInputCallRequest { |
||||
// Optional input payload sent along with the request. |
||||
optional Payload payload = 1; |
||||
|
||||
// Not expecting any payload from the response. |
||||
} |
||||
|
||||
// Client-streaming response. |
||||
message StreamingInputCallResponse { |
||||
// Aggregated size of payloads received from the client. |
||||
optional int32 aggregated_payload_size = 1; |
||||
} |
||||
|
||||
// Configuration for a particular response. |
||||
message ResponseParameters { |
||||
// Desired payload sizes in responses from the server. |
||||
// If response_type is COMPRESSABLE, this denotes the size before compression. |
||||
optional int32 size = 1; |
||||
|
||||
// Desired interval between consecutive responses in the response stream in |
||||
// microseconds. |
||||
optional int32 interval_us = 2; |
||||
} |
||||
|
||||
// Server-streaming request. |
||||
message StreamingOutputCallRequest { |
||||
// Desired payload type in the response from the server. |
||||
// If response_type is RANDOM, the payload from each response in the stream |
||||
// might be of different types. This is to simulate a mixed type of payload |
||||
// stream. |
||||
optional PayloadType response_type = 1; |
||||
|
||||
// Configuration for each expected response message. |
||||
repeated ResponseParameters response_parameters = 2; |
||||
|
||||
// Optional input payload sent along with the request. |
||||
optional Payload payload = 3; |
||||
} |
||||
|
||||
// Server-streaming response, as configured by the request and parameters. |
||||
message StreamingOutputCallResponse { |
||||
// Payload to increase response size. |
||||
optional Payload payload = 1; |
||||
} |
@ -0,0 +1,42 @@ |
||||
// An integration test service that covers all the method signature permutations |
||||
// of unary/streaming requests/responses. |
||||
syntax = "proto2"; |
||||
|
||||
import "empty.proto"; |
||||
import "messages.proto"; |
||||
|
||||
package grpc.testing; |
||||
|
||||
// A simple service to test the various types of RPCs and experiment with |
||||
// performance with various types of payload. |
||||
service TestService { |
||||
// One empty request followed by one empty response. |
||||
rpc EmptyCall(grpc.testing.Empty) returns (grpc.testing.Empty); |
||||
|
||||
// One request followed by one response. |
||||
// The server returns the client payload as-is. |
||||
rpc UnaryCall(SimpleRequest) returns (SimpleResponse); |
||||
|
||||
// One request followed by a sequence of responses (streamed download). |
||||
// The server returns the payload with client desired type and sizes. |
||||
rpc StreamingOutputCall(StreamingOutputCallRequest) |
||||
returns (stream StreamingOutputCallResponse); |
||||
|
||||
// A sequence of requests followed by one response (streamed upload). |
||||
// The server returns the aggregated size of client payload as the result. |
||||
rpc StreamingInputCall(stream StreamingInputCallRequest) |
||||
returns (StreamingInputCallResponse); |
||||
|
||||
// A sequence of requests with each request served by the server immediately. |
||||
// As one request could lead to multiple responses, this interface |
||||
// demonstrates the idea of full duplexing. |
||||
rpc FullDuplexCall(stream StreamingOutputCallRequest) |
||||
returns (stream StreamingOutputCallResponse); |
||||
|
||||
// A sequence of requests followed by a sequence of responses. |
||||
// The server buffers all the client requests and then serves them in order. A |
||||
// stream of responses are returned to the client when the server starts with |
||||
// first request. |
||||
rpc HalfDuplexCall(stream StreamingOutputCallRequest) |
||||
returns (stream StreamingOutputCallResponse); |
||||
} |
@ -0,0 +1,71 @@ |
||||
/* |
||||
* |
||||
* Copyright 2014, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
var interop_server = require('../interop/interop_server.js'); |
||||
var interop_client = require('../interop/interop_client.js'); |
||||
|
||||
var server; |
||||
|
||||
var port; |
||||
|
||||
var name_override = 'foo.test.google.com'; |
||||
|
||||
describe('Interop tests', function() { |
||||
before(function(done) { |
||||
var server_obj = interop_server.getServer(0, true); |
||||
server = server_obj.server; |
||||
server.listen(); |
||||
port = 'localhost:' + server_obj.port; |
||||
done(); |
||||
}); |
||||
// This depends on not using a binary stream
|
||||
it('should pass empty_unary', function(done) { |
||||
interop_client.runTest(port, name_override, 'empty_unary', true, done); |
||||
}); |
||||
it('should pass large_unary', function(done) { |
||||
interop_client.runTest(port, name_override, 'large_unary', true, done); |
||||
}); |
||||
it('should pass client_streaming', function(done) { |
||||
interop_client.runTest(port, name_override, 'client_streaming', true, done); |
||||
}); |
||||
it('should pass server_streaming', function(done) { |
||||
interop_client.runTest(port, name_override, 'server_streaming', true, done); |
||||
}); |
||||
it('should pass ping_pong', function(done) { |
||||
interop_client.runTest(port, name_override, 'ping_pong', true, done); |
||||
}); |
||||
// This depends on the new invoke API
|
||||
it.skip('should pass empty_stream', function(done) { |
||||
interop_client.runTest(port, name_override, 'empty_stream', true, done); |
||||
}); |
||||
}); |
@ -0,0 +1,83 @@ |
||||
# Copyright 2015, Google Inc. |
||||
# All rights reserved. |
||||
# |
||||
# Redistribution and use in source and binary forms, with or without |
||||
# modification, are permitted provided that the following conditions are |
||||
# met: |
||||
# |
||||
# * Redistributions of source code must retain the above copyright |
||||
# notice, this list of conditions and the following disclaimer. |
||||
# * Redistributions in binary form must reproduce the above |
||||
# copyright notice, this list of conditions and the following disclaimer |
||||
# in the documentation and/or other materials provided with the |
||||
# distribution. |
||||
# * Neither the name of Google Inc. nor the names of its |
||||
# contributors may be used to endorse or promote products derived from |
||||
# this software without specific prior written permission. |
||||
# |
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
"""A thread pool that logs exceptions raised by tasks executed within it.""" |
||||
|
||||
import functools |
||||
import logging |
||||
|
||||
from concurrent import futures |
||||
|
||||
|
||||
def _wrap(behavior): |
||||
"""Wraps an arbitrary callable behavior in exception-logging.""" |
||||
@functools.wraps(behavior) |
||||
def _wrapping(*args, **kwargs): |
||||
try: |
||||
return behavior(*args, **kwargs) |
||||
except Exception as e: |
||||
logging.exception('Unexpected exception from task run in logging pool!') |
||||
raise |
||||
return _wrapping |
||||
|
||||
|
||||
class _LoggingPool(object): |
||||
"""An exception-logging futures.ThreadPoolExecutor-compatible thread pool.""" |
||||
|
||||
def __init__(self, backing_pool): |
||||
self._backing_pool = backing_pool |
||||
|
||||
def __enter__(self): |
||||
return self |
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb): |
||||
self._backing_pool.shutdown(wait=True) |
||||
|
||||
def submit(self, fn, *args, **kwargs): |
||||
return self._backing_pool.submit(_wrap(fn), *args, **kwargs) |
||||
|
||||
def map(self, func, *iterables, **kwargs): |
||||
return self._backing_pool.map( |
||||
_wrap(func), *iterables, timeout=kwargs.get('timeout', None)) |
||||
|
||||
def shutdown(self, wait=True): |
||||
self._backing_pool.shutdown(wait=wait) |
||||
|
||||
|
||||
def pool(max_workers): |
||||
"""Creates a thread pool that logs exceptions raised by the tasks within it. |
||||
|
||||
Args: |
||||
max_workers: The maximum number of worker threads to allow the pool. |
||||
|
||||
Returns: |
||||
A futures.ThreadPoolExecutor-compatible thread pool that logs exceptions |
||||
raised by the tasks executed within it. |
||||
""" |
||||
return _LoggingPool(futures.ThreadPoolExecutor(max_workers)) |
@ -1,64 +1,63 @@ |
||||
Ruby for GRPC |
||||
============= |
||||
gRPC Ruby |
||||
========= |
||||
|
||||
LAYOUT |
||||
------ |
||||
A Ruby implementation of gRPC, Google's RPC library. |
||||
|
||||
Directory structure is the recommended layout for [ruby extensions](http://guides.rubygems.org/gems-with-extensions/) |
||||
|
||||
* ext: the extension code |
||||
* lib: the entrypoint grpc ruby library to be used in a 'require' statement |
||||
* test: tests |
||||
INSTALLATION PREREQUISITES |
||||
-------------------------- |
||||
|
||||
This requires Ruby 2.x, as the rpc api surface uses keyword args. |
||||
|
||||
DEPENDENCIES |
||||
------------ |
||||
|
||||
INSTALLING |
||||
---------- |
||||
|
||||
* Extension |
||||
- Install the gRPC core library |
||||
TODO: describe this, once the core distribution mechanism is defined. |
||||
|
||||
The extension can be built and tested using |
||||
[rake](https://rubygems.org/gems/rake). However, the rake-extensiontask rule |
||||
is not supported on older versions of rubygems, and the necessary version of |
||||
rubygems. |
||||
$ gem install grpc |
||||
|
||||
This is resolved by using [RVM](https://rvm.io/) instead; install a single-user |
||||
ruby environment, and develop on the latest stable version of ruby (2.1.5). |
||||
|
||||
Installing from source |
||||
---------------------- |
||||
|
||||
INSTALLATION PREREQUISITES |
||||
-------------------------- |
||||
|
||||
Install RVM |
||||
- Build or Install the gRPC core |
||||
E.g, from the root of the grpc [git repo](https://github.com/google/grpc) |
||||
$ cd ../.. |
||||
$ make && sudo make install |
||||
|
||||
- Install Ruby 2.x. Consider doing this with [RVM](http://rvm.io), it's a nice way of controlling |
||||
the exact ruby version that's used. |
||||
$ command curl -sSL https://rvm.io/mpapis.asc | gpg --import - |
||||
$ \curl -sSL https://get.rvm.io | bash -s stable --ruby |
||||
$ |
||||
$ # follow the instructions to ensure that your're using the latest stable version of Ruby |
||||
$ # and that the rvm command is installed |
||||
$ |
||||
$ gem install bundler # install bundler, the standard ruby package manager |
||||
|
||||
HACKING |
||||
------- |
||||
- Install [bundler](http://bundler.io/) |
||||
$ gem install bundler |
||||
|
||||
The extension can be built and tested using the Rakefile. |
||||
- Finally, install grpc ruby locally. |
||||
$ cd <install_dir> |
||||
$ bundle install |
||||
$ rake # compiles the extension, runs the unit tests, see rake -T for other options |
||||
|
||||
$ # create a workspace |
||||
$ git5 start <your-git5-branch> net/grpc |
||||
$ |
||||
$ # build the C library and install it in $HOME/grpc_dev |
||||
$ <google3>/net/grpc/c/build_gyp/build_grpc_dev.sh |
||||
$ |
||||
$ # build the ruby extension and test it. |
||||
$ cd google3_dir/net/grpc/ruby |
||||
$ rake |
||||
|
||||
Finally, install grpc ruby locally. |
||||
CONTENTS |
||||
-------- |
||||
|
||||
$ cd <this_dir> |
||||
$ |
||||
$ # update the Gemfile, modify the line beginning # gem 'beefcake' to refer to |
||||
$ # the patched beefcake dir |
||||
$ |
||||
$ bundle install |
||||
Directory structure is the layout for [ruby extensions](http://guides.rubygems.org/gems-with-extensions/) |
||||
|
||||
* ext: the extension code |
||||
* lib: the entrypoint grpc ruby library to be used in a 'require' statement |
||||
* spec: tests |
||||
* bin: example gRPC clients and servers, e.g, |
||||
```ruby |
||||
# client |
||||
stub = Math::Math::Stub.new('my.test.math.server.com:8080') |
||||
req = Math::DivArgs.new(dividend: 7, divisor: 3) |
||||
logger.info("div(7/3): req=#{req.inspect}") |
||||
resp = stub.div(req, INFINITE_FUTURE) |
||||
logger.info("Answer: #{resp.inspect}") |
||||
``` |
||||
|
@ -1,11 +1,8 @@ |
||||
Interop test protos |
||||
=================== |
||||
|
||||
These were generated by a patched version of beefcake and a patched version of |
||||
protoc. |
||||
These ruby classes were generated with protoc v3, using grpc's ruby compiler |
||||
plugin. |
||||
|
||||
- set up and access of the patched versions is described in ../../README.md |
||||
|
||||
The actual test proto is found in Google3 at |
||||
|
||||
- third_party/stubby/testing/proto/test.proto |
||||
- As of 2015/01 protoc v3 is available in the |
||||
[google-protobuf](https://github.com/google/protobuf) repo |
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue