pulsar-client 2.4.1.pre.beta.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,31 @@
1
+ #ifndef __PULSAR_RUBY_CLIENT_CONSUMER_HPP
2
+ #define __PULSAR_RUBY_CLIENT_CONSUMER_HPP
3
+
4
+ #include "rice/Module.hpp"
5
+ #include "rice/Data_Object.hpp"
6
+ #include <pulsar/Client.h>
7
+
8
+ #include "message.hpp"
9
+
10
+ namespace pulsar_rb {
11
+ class Consumer {
12
+ public:
13
+ pulsar::Consumer _consumer;
14
+ Consumer() {};
15
+ Consumer(const pulsar::Consumer& consumer) : _consumer(consumer) {}
16
+
17
+ Message::ptr receive();
18
+ void acknowledge(const Message& message);
19
+ void negative_acknowledge(const Message& message);
20
+
21
+ typedef Rice::Data_Object<Consumer> ptr;
22
+ };
23
+
24
+ // direct typedef instead of wrapping because implementations don't need any
25
+ // wrapping. but still re-namespaced for consistency
26
+ typedef pulsar::ConsumerConfiguration ConsumerConfiguration;
27
+ };
28
+
29
+ void bind_consumer(Rice::Module& module);
30
+
31
+ #endif
@@ -0,0 +1,3 @@
1
+ require 'mkmf-rice'
2
+ $LOCAL_LIBS << "-lpulsar"
3
+ create_makefile('pulsar/bindings')
@@ -0,0 +1,47 @@
1
+ #include "rice/Data_Type.hpp"
2
+ #include "rice/Constructor.hpp"
3
+ #include <pulsar/Client.h>
4
+
5
+ #include "message.hpp"
6
+
7
+ namespace pulsar_rb {
8
+
9
+ Rice::String MessageId::toString() {
10
+ std::stringstream ss;
11
+ ss << _msgId;
12
+ return Rice::String(ss.str());
13
+ }
14
+
15
+ Message::Message(const std::string& data) {
16
+ pulsar::MessageBuilder mb;
17
+ mb.setContent(data);
18
+ _msg = mb.build();
19
+ }
20
+
21
+ Rice::String Message::getData() {
22
+ std::string str((const char*)_msg.getData(), _msg.getLength());
23
+ return Rice::String(str);
24
+ }
25
+
26
+ MessageId::ptr Message::getMessageId() {
27
+ pulsar::MessageId messageId = _msg.getMessageId();
28
+ return MessageId::ptr(new MessageId(messageId));
29
+ }
30
+
31
+ }
32
+
33
+ using namespace Rice;
34
+
35
+ void bind_message(Module& module) {
36
+ define_class_under<pulsar_rb::MessageId>(module, "MessageId")
37
+ .define_constructor(Constructor<pulsar_rb::MessageId, const pulsar::MessageId&>())
38
+ .define_method("to_s", &pulsar_rb::MessageId::toString)
39
+ ;
40
+
41
+ define_class_under<pulsar_rb::Message>(module, "Message")
42
+ .define_constructor(Constructor<pulsar_rb::Message, const pulsar::Message&>())
43
+ .define_constructor(Constructor<pulsar_rb::Message, const std::string&>())
44
+ .define_method("data", &pulsar_rb::Message::getData)
45
+ .define_method("message_id", &pulsar_rb::Message::getMessageId)
46
+ ;
47
+ }
@@ -0,0 +1,35 @@
1
+ #ifndef __PULSAR_RUBY_CLIENT_MESSAGE_HPP
2
+ #define __PULSAR_RUBY_CLIENT_MESSAGE_HPP
3
+
4
+ #include "rice/Module.hpp"
5
+ #include "rice/String.hpp"
6
+ #include "rice/Data_Object.hpp"
7
+ #include <pulsar/Client.h>
8
+
9
+ namespace pulsar_rb {
10
+ class MessageId {
11
+ public:
12
+ pulsar::MessageId _msgId;
13
+ MessageId(const pulsar::MessageId& msgId) : _msgId(msgId) {};
14
+
15
+ Rice::String toString();
16
+
17
+ typedef Rice::Data_Object<MessageId> ptr;
18
+ };
19
+
20
+ class Message {
21
+ public:
22
+ pulsar::Message _msg;
23
+ Message(const pulsar::Message& msg) : _msg(msg) {};
24
+ Message(const std::string& data);
25
+
26
+ Rice::String getData();
27
+ MessageId::ptr getMessageId();
28
+
29
+ typedef Rice::Data_Object<Message> ptr;
30
+ };
31
+ };
32
+
33
+ void bind_message(Rice::Module& module);
34
+
35
+ #endif
@@ -0,0 +1,69 @@
1
+ #include "rice/Data_Type.hpp"
2
+ #include "rice/Constructor.hpp"
3
+ #include <pulsar/Client.h>
4
+ #include <ruby/thread.h>
5
+
6
+ #include "producer.hpp"
7
+ #include "util.hpp"
8
+
9
+ namespace pulsar_rb {
10
+
11
+ typedef struct {
12
+ pulsar::Producer& producer;
13
+ const pulsar::Message& message;
14
+ pulsar::Result result;
15
+ } producer_send_task;
16
+
17
+ void* producer_send_worker(void* taskPtr) {
18
+ producer_send_task& task = *(producer_send_task*)taskPtr;
19
+ task.result = task.producer.send(task.message);
20
+ return nullptr;
21
+ }
22
+
23
+ void Producer::send(const Message& message) {
24
+ producer_send_task task = { _producer, message._msg };
25
+ rb_thread_call_without_gvl(&producer_send_worker, &task, RUBY_UBF_IO, nullptr);
26
+ CheckResult(task.result);
27
+ }
28
+
29
+ }
30
+
31
+ using namespace Rice;
32
+
33
+ void bind_producer(Module& module) {
34
+ define_class_under<pulsar_rb::Producer>(module, "Producer")
35
+ .define_constructor(Constructor<pulsar_rb::Producer>())
36
+ .define_method("send", &pulsar_rb::Producer::send)
37
+ ;
38
+
39
+ define_class_under<pulsar_rb::ProducerConfiguration>(module, "ProducerConfiguration")
40
+ .define_constructor(Constructor<pulsar_rb::ProducerConfiguration>())
41
+ .define_method("producer_name", &ProducerConfiguration::getProducerName)
42
+ .define_method("producer_name=", &ProducerConfiguration::setProducerName)
43
+ // TODO .define_method("schema", &ProducerConfiguration::getSchema)
44
+ // TODO .define_method("schema=", &ProducerConfiguration::setSchema)
45
+ .define_method("send_timeout_millis", &ProducerConfiguration::getSendTimeout)
46
+ .define_method("send_timeout_millis=", &ProducerConfiguration::setSendTimeout)
47
+ .define_method("initial_sequence_id", &ProducerConfiguration::getInitialSequenceId)
48
+ .define_method("initial_sequence_id=", &ProducerConfiguration::setInitialSequenceId)
49
+ .define_method("compression_type", &ProducerConfiguration::getCompressionType)
50
+ .define_method("compression_type=", &ProducerConfiguration::setCompressionType)
51
+ .define_method("max_pending_messages", &ProducerConfiguration::getMaxPendingMessages)
52
+ .define_method("max_pending_messages=", &ProducerConfiguration::setMaxPendingMessages)
53
+ .define_method("max_pending_messages_across_partitions", &ProducerConfiguration::getMaxPendingMessagesAcrossPartitions)
54
+ .define_method("max_pending_messages_across_partitions=", &ProducerConfiguration::setMaxPendingMessagesAcrossPartitions)
55
+ .define_method("block_if_queue_full", &ProducerConfiguration::getBlockIfQueueFull)
56
+ .define_method("block_if_queue_full=", &ProducerConfiguration::setBlockIfQueueFull)
57
+ .define_method("partitions_routing_mode", &ProducerConfiguration::getPartitionsRoutingMode)
58
+ .define_method("partitions_routing_mode=", &ProducerConfiguration::setPartitionsRoutingMode)
59
+ .define_method("batching_enabled", &ProducerConfiguration::getBatchingEnabled)
60
+ .define_method("batching_enabled=", &ProducerConfiguration::setBatchingEnabled)
61
+ .define_method("batching_max_messages", &ProducerConfiguration::getBatchingMaxMessages)
62
+ .define_method("batching_max_messages=", &ProducerConfiguration::setBatchingMaxMessages)
63
+ .define_method("batching_max_allowed_size_in_bytes", &ProducerConfiguration::getBatchingMaxAllowedSizeInBytes)
64
+ .define_method("batching_max_allowed_size_in_bytes=", &ProducerConfiguration::setBatchingMaxAllowedSizeInBytes)
65
+ .define_method("batching_max_publish_delay_ms", &ProducerConfiguration::getBatchingMaxPublishDelayMs)
66
+ .define_method("batching_max_publish_delay_ms=", &ProducerConfiguration::setBatchingMaxPublishDelayMs)
67
+ .define_method("[]", &ProducerConfiguration::getProperty)
68
+ .define_method("[]=", &ProducerConfiguration::setProperty);
69
+ }
@@ -0,0 +1,29 @@
1
+ #ifndef __PULSAR_RUBY_CLIENT_PRODUCER_HPP
2
+ #define __PULSAR_RUBY_CLIENT_PRODUCER_HPP
3
+
4
+ #include "rice/Module.hpp"
5
+ #include "rice/Data_Object.hpp"
6
+ #include <pulsar/Client.h>
7
+
8
+ #include "message.hpp"
9
+
10
+ namespace pulsar_rb {
11
+ class Producer {
12
+ public:
13
+ pulsar::Producer _producer;
14
+ Producer() {};
15
+ Producer(const pulsar::Producer& producer) : _producer(producer) {}
16
+
17
+ void send(const Message& message);
18
+
19
+ typedef Rice::Data_Object<Producer> ptr;
20
+ };
21
+
22
+ // direct typedef instead of wrapping because implementations don't need any
23
+ // wrapping. but still re-namespaced for consistency
24
+ typedef pulsar::ProducerConfiguration ProducerConfiguration;
25
+ };
26
+
27
+ void bind_producer(Rice::Module& module);
28
+
29
+ #endif
@@ -0,0 +1,11 @@
1
+ #include <pulsar/Client.h>
2
+
3
+ #include "util.hpp"
4
+
5
+ using namespace pulsar;
6
+
7
+ void CheckResult(Result res) {
8
+ if (res != ResultOk) {
9
+ throw PulsarException(res);
10
+ }
11
+ }
@@ -0,0 +1,16 @@
1
+ #ifndef __PULSAR_RUBY_CLIENT_UTIL_HPP
2
+ #define __PULSAR_RUBY_CLIENT_UTIL_HPP
3
+
4
+ #include <pulsar/Client.h>
5
+
6
+ using namespace pulsar;
7
+
8
+ struct PulsarException {
9
+ Result _result;
10
+ PulsarException(Result res) :
11
+ _result(res) {}
12
+ };
13
+
14
+ void CheckResult(Result res);
15
+
16
+ #endif
@@ -0,0 +1,58 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+
20
+ require 'pulsar/client/version'
21
+ require 'pulsar/bindings'
22
+ require 'pulsar/client_configuration'
23
+ require 'pulsar/consumer'
24
+ require 'pulsar/consumer_configuration'
25
+ require 'pulsar/producer'
26
+
27
+ module Pulsar
28
+ class Client
29
+ module RubySideTweaks
30
+ def initialize(service_url, config=nil)
31
+ config = Pulsar::ClientConfiguration.from(config)
32
+ super(service_url, config)
33
+ end
34
+
35
+ def create_producer(topic, config=nil)
36
+ config ||= Pulsar::ProducerConfiguration.new
37
+ super(topic, config)
38
+ end
39
+
40
+ def subscribe(topic, subscription_name, config=nil)
41
+ config ||= Pulsar::ConsumerConfiguration.new
42
+ super(topic, subscription_name, config)
43
+ end
44
+ end
45
+
46
+ prepend RubySideTweaks
47
+
48
+ def self.sufficient_environment?(config={})
49
+ config[:broker_uri] || ENV['PULSAR_BROKER_URI']
50
+ end
51
+
52
+ def self.from_environment(config={})
53
+ broker_uri = config[:broker_uri] || ENV['PULSAR_BROKER_URI']
54
+ config = Pulsar::ClientConfiguration.from_environment(config)
55
+ new(broker_uri, config)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,24 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+
20
+ module Pulsar
21
+ class Client
22
+ VERSION = "2.4.1-beta.1"
23
+ end
24
+ end
@@ -0,0 +1,77 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+
20
+ require 'pulsar/bindings'
21
+
22
+ module Pulsar
23
+ class ClientConfiguration
24
+ def self.from(config)
25
+ case config
26
+ when self then config # already a config object
27
+ when nil then self.new # empty (all defaults) config object
28
+ when Hash then self.new(config) # config object from hash
29
+ else raise ArgumentError
30
+ end
31
+ end
32
+
33
+ def self.from_environment(config={})
34
+ env_config = {}
35
+ if ENV.key?('PULSAR_CERT_PATH')
36
+ env_config[:use_tls] = true
37
+ env_config[:tls_allow_insecure_connection] = false
38
+ env_config[:tls_validate_hostname] = false
39
+ env_config[:tls_trust_certs_file_path] = ENV['PULSAR_CERT_PATH']
40
+ end
41
+ if ENV.key?('PULSAR_AUTH_TOKEN')
42
+ env_config[:authentication_token] = ENV['PULSAR_AUTH_TOKEN']
43
+ end
44
+ self.from(env_config.merge(config))
45
+ end
46
+
47
+ module RubySideTweaks
48
+ def initialize(config={})
49
+ super()
50
+ populate(config)
51
+ end
52
+ end
53
+
54
+ prepend RubySideTweaks
55
+
56
+ def populate(config={})
57
+ populate_one(config, :authentication_token)
58
+ populate_one(config, :operation_timeout_seconds)
59
+ populate_one(config, :io_threads)
60
+ populate_one(config, :message_listener_threads)
61
+ populate_one(config, :concurrent_lookup_requests)
62
+ populate_one(config, :log_conf_file_path)
63
+ populate_one(config, :use_tls)
64
+ populate_one(config, :tls_trust_certs_file_path)
65
+ populate_one(config, :tls_allow_insecure_connection)
66
+ populate_one(config, :tls_validate_hostname)
67
+ end
68
+
69
+ def populate_one(config, key)
70
+ if config.key?(key)
71
+ self.send(:"#{key}=", config[key])
72
+ elsif config.key?(key.to_s)
73
+ self.send(:"#{key}=", config[key.to_s])
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,51 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+
20
+ require 'pulsar/bindings'
21
+
22
+ module Pulsar
23
+ class Consumer
24
+ class ListenerToken
25
+ def initialize
26
+ @active = true
27
+ end
28
+
29
+ def finish
30
+ @active = false
31
+ end
32
+
33
+ def active?
34
+ @active
35
+ end
36
+ end
37
+
38
+ def listen
39
+ listener = ListenerToken.new
40
+ while listener.active?
41
+ msg = receive
42
+ yield msg.data, msg.message_id, lambda { listener.finish }
43
+ acknowledge(msg)
44
+ end
45
+ end
46
+
47
+ def listen_in_thread
48
+ Thread.new { listen }
49
+ end
50
+ end
51
+ end