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.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/CONTRIBUTORS.md +26 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +40 -0
- data/LICENSE +202 -0
- data/NOTICE +6 -0
- data/README.md +89 -0
- data/Rakefile +10 -0
- data/TODO.md +24 -0
- data/bin/console +8 -0
- data/bin/example-consumer +45 -0
- data/bin/example-producer +43 -0
- data/bin/setup +6 -0
- data/ext/bindings/bindings.cpp +18 -0
- data/ext/bindings/client.cpp +187 -0
- data/ext/bindings/client.hpp +56 -0
- data/ext/bindings/consumer.cpp +90 -0
- data/ext/bindings/consumer.hpp +31 -0
- data/ext/bindings/extconf.rb +3 -0
- data/ext/bindings/message.cpp +47 -0
- data/ext/bindings/message.hpp +35 -0
- data/ext/bindings/producer.cpp +69 -0
- data/ext/bindings/producer.hpp +29 -0
- data/ext/bindings/util.cpp +11 -0
- data/ext/bindings/util.hpp +16 -0
- data/lib/pulsar/client.rb +58 -0
- data/lib/pulsar/client/version.rb +24 -0
- data/lib/pulsar/client_configuration.rb +77 -0
- data/lib/pulsar/consumer.rb +51 -0
- data/lib/pulsar/consumer_configuration.rb +55 -0
- data/lib/pulsar/producer.rb +35 -0
- data/pulsar-client.gemspec +31 -0
- metadata +149 -0
@@ -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,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,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
|