I'm using the following code to try connecting to the Pub/Sub emulator running on localhost. It's basically a direct copy of the example code with the ServiceEndpoint changed.
TopicName topicName = new TopicName(projectId, topicId);
var endpoint = new ServiceEndpoint("localhost", 8085);
SubscriberClient subscriber = await SubscriberClient.CreateAsync(endpoint);
SubscriptionName subscriptionName = new SubscriptionName(projectId, "test-sub");
subscriber.CreateSubscription(subscriptionName, topicName, pushConfig: null, ackDeadlineSeconds: 60);
No errors are thrown but no messages are received either. Looking at the emulator logs I see:
[pubsub] INFO: Adding handler(s) to newly registered Channel.
[pubsub] Jan 08, 2018 10:50:10 PM io.gapi.emulators.netty.HttpVersionRoutingHandler channelRead
[pubsub] INFO: Detected non-HTTP/2 connection.
[pubsub] Jan 08, 2018 10:50:10 PM io.gapi.emulators.netty.NotFoundHandler handleRequest
[pubsub] INFO: Unknown request URI: /bad-request
A quick google let me to https://stackoverflow.com/questions/43657112/creating-topic-on-pubsub-emulator suggesting that the solution for the Java library is to create a custom ChannelProvider and have it use NegotiationType.PLAINTEXT as this is required by the emulator.
This led me to try using insecure GRPC which works for the SimpleSubscriber:
var settings = new SimpleSubscriber.ClientCreationSettings(null, null, ChannelCredentials.Insecure, endpoint);
SimpleSubscriber simpleSubscriber = await SimpleSubscriber.CreateAsync(subscriptionName, settings);
but not the SubscriberClient needed to create a topic. I see a way to change the CallCredentials for the
SubscriberClient but can't figure out how to switch it to insecure. This may be to my relative lack of understanding of the gRPC setup.
Any insight on how to get this working?
Also an example of using these libraries with the emulators would be helpful. It's one of the first places developers are going to start experimenting with the libraries and the experience so far hasn't been smooth for me (not specific to the c# libraries, am testing with others as well).
See https://googlecloudplatform.github.io/google-cloud-dotnet/docs/faq.html#how-can-i-use-emulators for this - basically you need to create a channel and pass that into SubscriberClient.Create.
Please check whether this works for you - I'll assign this to Chris to look into if you have any more issues.
That worked perfectly, not sure how I missed that. Spent an hour searching for a solution but somehow missed the synchronous Create() that accepts a preconfigured Channel.
@jskeet creating channels will work for sync, wondering if there is the same configuration for async functions
@cariquitanmac: I'm not quite sure what you mean. The only part that needs to be asynchronous in client creation is obtaining credentials. You can then create the channel, and pass it synchronously to the client creation methods... all the async methods within the client should be fine.
@jskeet
My concern is after adding channel the code will become lengthy compared to the original one.
New Revision:
TopicName topic = new TopicName(ProjectId, TopicId);
string emulatorHostAndPort = Environment.GetEnvironmentVariable("PUBSUB_EMULATOR_HOST", EnvironmentVariableTarget.User);
Channel channel = new Channel(emulatorHostAndPort, ChannelCredentials.Insecure);
PublisherServiceApiClient publisherService = PublisherServiceApiClient.Create(channel);
List<PubsubMessage> messages = new List<PubsubMessage>();
var pubMessage = new PubsubMessage
{
Data = ByteString.CopyFromUtf8("Hello Cloud Pub/Sub!"),
// The attributes provide metadata in a string-to-string
// dictionary.
Attributes =
{
{ "description", "Simple text message" }
}
};
messages.Add(pubMessage);
var messageId = await publisherService.PublishAsync(topic, messages);
Original Copy:
```
TopicName topic = new TopicName(ProjectId, TopicId);
PublisherClient publisher = await PublisherClient.CreateAsync(topic);
string messageId = await publisher.PublishAsync("Hello World");
// Publisher client must be shutdown after use
await publisher.ShutdownAsync(TimeSpan.FromSeconds(15));
```
And I want to retain the original version wherever the code is deployed local/cloud. Maybe I missed something XD
No, that should be absolutely fine. I don't think any of that creation code would be performing any IO.
@jskeet Last thing, will this channel creation code block will still run when I hosted my application in cloud? Don't see this variable in envi list
Well there's nothing conditional in your code, so yes, it will still run. If you want to stop it from running when the environment variable is missing or empty, you'd write code to do that.
Most helpful comment
See https://googlecloudplatform.github.io/google-cloud-dotnet/docs/faq.html#how-can-i-use-emulators for this - basically you need to create a channel and pass that into SubscriberClient.Create.
Please check whether this works for you - I'll assign this to Chris to look into if you have any more issues.