pulsar-client 2.4.1.pre.beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|