From 9c287acfe6134e3188f9b3586346e5c83cbba3b1 Mon Sep 17 00:00:00 2001 From: ShannonDing Date: Tue, 4 Sep 2018 12:13:28 +0800 Subject: [PATCH] Update C++ API reflect OpenMessaging JavaAPI V1.0.0-preveiw --- BuiltinKeys.h | 262 --------------- ByteMessage.h | 16 + Future.h | 47 +++ FutureListener.h | 20 ++ Headers.h | 335 +++++++++++++++++++ KeyValue.h | 20 ++ Message.h | 40 ++- MessageFactory.h | 18 +- MessagingAccessPoint.h | 44 ++- Namespace.h | 16 + OMS.h | 16 + OMSBuiltinKeys.h | 32 ++ OMSException.h | 25 -- OMSResponseStatus.h | 53 +++ OpenMessaging.h | 18 +- Promise.h | 16 + README.md | 10 +- ResourceManager.h | 205 ------------ ServiceLifecycle.h | 16 + Uncopyable.h | 16 + assets/images/OpenMessaging-V0.2.0-alpha.png | Bin 54064 -> 0 bytes assets/images/OpenMessaging-V0.3.0-alpha.png | Bin 58165 -> 0 bytes assets/images/domain-design.png | Bin 52377 -> 0 bytes consumer/Consumer.h | 138 ++++++++ consumer/Context.h | 23 +- consumer/MessageListener.h | 26 +- consumer/PullConsumer.h | 91 ----- consumer/PushConsumer.h | 117 ------- consumer/StreamingConsumer.h | 39 --- consumer/StreamingIterator.h | 35 -- interceptor/ConsumerInterceptor.h | 37 +- interceptor/InterceptorContext.h | 42 +++ interceptor/ProducerInterceptor.h | 34 +- manager/ResourceManager.h | 130 +++++++ observer/OMSEvent.h | 29 -- observer/OMSExceptionEvent.h | 22 -- observer/Observer.h | 31 -- producer/BatchMessageSender.h | 35 -- producer/CheckContext.h | 28 +- producer/ExecutionContext.h | 25 -- producer/LocalTransactionExecutor.h | 43 --- producer/Producer.h | 69 ++-- producer/SendResult.h | 16 + producer/TransactionStateCheckListener.h | 62 ++++ producer/TransactionalSendResult.h | 63 ++++ routing/Operator.h | 34 -- routing/Routing.h | 31 -- samples/ProducerApp.cpp | 73 ++++ samples/PullConsumerApp.cpp | 54 +++ shared_ptr.hpp | 20 +- smart_pointer.h | 18 +- 51 files changed, 1449 insertions(+), 1141 deletions(-) delete mode 100644 BuiltinKeys.h create mode 100644 Headers.h create mode 100644 OMSBuiltinKeys.h delete mode 100644 OMSException.h create mode 100644 OMSResponseStatus.h delete mode 100644 ResourceManager.h delete mode 100644 assets/images/OpenMessaging-V0.2.0-alpha.png delete mode 100644 assets/images/OpenMessaging-V0.3.0-alpha.png delete mode 100644 assets/images/domain-design.png create mode 100644 consumer/Consumer.h delete mode 100644 consumer/PullConsumer.h delete mode 100644 consumer/PushConsumer.h delete mode 100644 consumer/StreamingConsumer.h delete mode 100644 consumer/StreamingIterator.h create mode 100644 interceptor/InterceptorContext.h create mode 100644 manager/ResourceManager.h delete mode 100644 observer/OMSEvent.h delete mode 100644 observer/OMSExceptionEvent.h delete mode 100644 observer/Observer.h delete mode 100644 producer/BatchMessageSender.h delete mode 100644 producer/ExecutionContext.h delete mode 100644 producer/LocalTransactionExecutor.h create mode 100644 producer/TransactionStateCheckListener.h create mode 100644 producer/TransactionalSendResult.h delete mode 100644 routing/Operator.h delete mode 100644 routing/Routing.h create mode 100644 samples/ProducerApp.cpp create mode 100644 samples/PullConsumerApp.cpp diff --git a/BuiltinKeys.h b/BuiltinKeys.h deleted file mode 100644 index 44f90d4..0000000 --- a/BuiltinKeys.h +++ /dev/null @@ -1,262 +0,0 @@ -#ifndef OMS_BUILTIN_KEYS_H -#define OMS_BUILTIN_KEYS_H - -#include -#include "Namespace.h" - -BEGIN_NAMESPACE_2(io, openmessaging) - - /** - * The {@code MESSAGE_ID} header field contains a value that uniquely identifies - * each message sent by a {@code Producer}. - *

- * When a message is sent, MESSAGE_ID is assigned by the producer. - */ - static const std::string MESSAGE_ID = "MESSAGE_ID"; - - /** - * The {@code DESTINATION} header field contains the destination to which the message is being sent. - *

- * When a message is sent this value is set to the right {@code Queue}, then the message will be sent to - * the specified destination. - *

- * When a message is received, its destination is equivalent to the {@code Queue} where the message resides in. - */ - static const std::string DESTINATION = "DESTINATION"; - - /** - * The {@code RECEIPT_HANDLE} header field contains an identifier associated with the act of receiving a message. - *

- * A new receipt handle will be set properly every time a message is received, and the consumer could use - * it to acknowledge the consumed message. - */ - static const std::string RECEIPT_HANDLE = "RECEIPT_HANDLE"; - - /** - * The {@code BORN_TIMESTAMP} header field contains the time a message was handed - * off to a {@code Producer} to be sent. - *

- * When a message is sent, BORN_TIMESTAMP will be set with current timestamp as the born - * timestamp of a message in client side, on return from the send method, the message's - * BORN_TIMESTAMP header field contains this value. - *

- * When a message is received its, BORN_TIMESTAMP header field contains this same value. - *

- * This filed is a {@code long} value, measured in milliseconds. - */ - static const std::string BORN_TIMESTAMP = "BORN_TIMESTAMP"; - - /** - * The {@code BORN_HOST} header field contains the born host info of a message in client side. - *

- * When a message is sent, BORN_HOST will be set with the local host info, - * on return from the send method, the message's BORN_HOST header field contains this value. - *

- * When a message is received, its BORN_HOST header field contains this same value. - */ - static const std::string BORN_HOST = "BORN_HOST"; - - /** - * The {@code STORE_TIMESTAMP} header field contains the store timestamp of a message in server side. - *

- * When a message is sent, STORE_TIMESTAMP is ignored. - *

- * When the send method returns it contains a server-assigned value. - *

- * This filed is a {@code long} value, measured in milliseconds. - */ - static const std::string STORE_TIMESTAMP = "STORE_TIMESTAMP"; - - /** - * The {@code STORE_HOST} header field contains the store host info of a message in server side. - *

- * When a message is sent, STORE_HOST is ignored. - *

- * When the send method returns it contains a server-assigned value. - */ - static const std::string STORE_HOST = "STORE_HOST"; - - /** - * The {@code START_TIME} header field contains the startup timestamp that a message - * can be delivered to consumer client. - *

- * If START_TIME field isn't set explicitly, use BORN_TIMESTAMP as the startup timestamp. - *

- * This filed is a {@code long} value, measured in milliseconds. - */ - static const std::string START_TIME = "START_TIME"; - - /** - * The {@code STOP_TIME} header field contains the stop timestamp that a message - * should be discarded after this timestamp, and no consumer can consume this message. - *

- * {@code (START_TIME ~ STOP_TIME)} represents an absolute valid interval that a message - * can be delivered in it. - *

- * If an earlier timestamp is set than START_TIME, that means the message does not expire. - *

- * This filed is a {@code long} value, measured in milliseconds. - *

- * When an undelivered message's expiration time is reached, the message should be destroyed. - * OMS does not define a notification of message expiration. - */ - static const std::string STOP_TIME = "STOP_TIME"; - - /** - * The {@code TIMEOUT} header field contains the expiration time, it represents a - * time-to-live value. - *

- * {@code (BORN_TIMESTAMP ~ BORN_TIMESTAMP + TIMEOUT)} represents a relative valid interval - * that a message can be delivered in it. - * If the TIMEOUT field is specified as zero, that indicates the message does not expire. - *

- * The TIMEOUT header field has higher priority than START_TIME/STOP_TIME header fields. - *

- * When an undelivered message's expiration time is reached, the message should be destroyed. - * OMS does not define a notification of message expiration. - */ - static const std::string TIMEOUT = "TIMEOUT"; - - /** - * The {@code PRIORITY} header field contains the priority level of a message, - * a message with a higher priority value should be delivered preferentially. - *

- * OMS defines a ten level priority value with 1 as the lowest priority and 10 as the highest, - * and the default priority is 5. The priority beyond this region will be ignored. - *

- * OMS does not require or provide any guarantee that the message should be delivered - * in priority order strictly, but the vendor should provide a best effort to - * deliver expedited messages ahead of normal messages. - *

- * If PRIORITY field isn't set explicitly, use {@code 5} as the default priority. - */ - static const std::string PRIORITY = "PRIORITY"; - - /** - * The {@code RELIABILITY} header field contains the reliability level of a message, the vendor - * should guarantee the reliability level for a message. - *

- * OMS defines two modes of message delivery: - *

- */ - static const std::string RELIABILITY = "RELIABILITY"; - - /** - * The {@code SEARCH_KEYS} header field contains the multiple search keys of a message. - *

- * The keyword indexes will be built by the search keys, users can query similar - * messages through these indexes and have a quick response. - *

- * This field is a {@code String} value, the different search keys are joined - * together with a comma delimiter. - *

- * OMS defines that a message at most has five search keys. - */ - static const std::string SEARCH_KEYS = "SEARCH_KEYS"; - - /** - * The {@code SCHEDULE_EXPRESSION} header field contains schedule expression of a message. - *

- * The message will be delivered by the specified SCHEDULE_EXPRESSION, which is a CRON expression. - * - * @see https://en.wikipedia.org/wiki/Cron#CRON_expression - */ - static const std::string SCHEDULE_EXPRESSION = "SCHEDULE_EXPRESSION"; - - /** - * The {@code TRACE_ID} header field contains the trace ID of a message, which represents a global and unique - * identification, to associate key events in the whole lifecycle of a message, - * like sent by who, stored at where, and received by who. - *

- * And, the messaging system only plays exchange role in a distributed system in most cases, - * so the TraceID can be used to trace the whole call link with other parts in the whole system. - */ - static const std::string TRACE_ID = "TRACE_ID"; - - /** - * The {@code STREAM_KEY} header field contains the stream key of a message. - * The messages with same stream key should be dispatched to the same stream of the queue. - */ - static const std::string STREAM_KEY = "STREAM_KEY"; - - /** - * The {@code REDELIVERED_NUMBER} header field contains a number, which represents - * the number of message delivery. - */ - static const std::string REDELIVERED_NUMBER = "REDELIVERED_NUMBER"; - - /** - * The {@code REDELIVERED_REASON} header field contains the text description of the reason that causes - * the last message delivery retry. - */ - static const std::string REDELIVERED_REASON = "REDELIVERED_REASON"; - - /** - * The {@code DRIVER_IMPL} key represents the vendor implementation - * entry of {@link MessagingAccessPoint}. - */ - static const std::string DRIVER_IMPL = "DRIVER_IMPL"; - - /** - * The {@code ACCESS_POINTS} key shows the specified access points in OMS driver schema. - * @see Access Point Schema - */ - static const std::string ACCESS_POINTS = "ACCESS_POINTS"; - - /** - * The {@code ACCOUNT_ID} key shows the specified account info in OMS driver schema. - */ - static const std::string ACCOUNT_ID = "ACCOUNT_ID"; - - /** - * The {@code REGION} key shows the specified region in OMS driver schema. - */ - static const std::string REGION = "REGION"; - - /** - * The {@code PRODUCER_ID} key represents the the unique producer id of a producer instance. - */ - static const std::string PRODUCER_ID = "PRODUCER_ID"; - - /** - * The {@code CONSUMER_ID} key represents the the unique consumer id of a consumer instance. - */ - static const std::string CONSUMER_ID = "CONSUMER_ID"; - - /** - * The {@code OPERATION_TIMEOUT} key defines the timeout of almost all the method calls in OMS. - */ - static const std::string OPERATION_TIMEOUT = "OPERATION_TIMEOUT"; - - /** - * The {@code ROUTING_SOURCE} key shows the source queue of a {@code Routing} instance. - *

- * The {@code Routing} consists of a triple, include source queue, destination queue and expression. - */ - static const std::string ROUTING_SOURCE = "ROUTING_SOURCE"; - - /** - * The {@code ROUTING_DESTINATION} key shows the destination queue of a {@code Routing} instance. - *

- * The {@code Routing} consists of a triple, include source queue, destination queue and expression. - */ - static const std::string ROUTING_DESTINATION = "ROUTING_DESTINATION"; - - /** - * The {@code ROUTING_EXPRESSION} key shows the expression of a {@code Routing} instance. - *

- * The {@code Routing} consists of a triple, include source queue, destination queue and expression. - */ - static const std::string ROUTING_EXPRESSION = "ROUTING_EXPRESSION"; - -END_NAMESPACE_2(io, openmessaging) -#endif // OMS_BUILTIN_KEYS_H diff --git a/ByteMessage.h b/ByteMessage.h index bc3dcea..77acc34 100644 --- a/ByteMessage.h +++ b/ByteMessage.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_BYTE_MESSAGE_H #define OMS_BYTE_MESSAGE_H diff --git a/Future.h b/Future.h index 0c10441..b33c884 100644 --- a/Future.h +++ b/Future.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_FUTURE_H #define OMS_FUTURE_H @@ -24,14 +40,45 @@ BEGIN_NAMESPACE_2(io, openmessaging) } + /** + * Returns {@code true} if this task was cancelled before it completed normally. + * + * @return {@code true} if this task was cancelled before it completed + */ virtual bool isCancelled() = 0; + /** + * Returns {@code true} if this task completed. + *

+ * Completion may be due to normal termination, an exception, or cancellation -- in all of these cases, this method + * will return {@code true}. + * + * @return {@code true} if this task completed + */ virtual bool isDone() = 0; + /** + * Waits if necessary for at most the given time for the computation to complete, and then retrieves its result, if + * available. + * + * @param timeout the maximum time to wait + * @return the computed result

if the computation was cancelled + */ virtual producer::SendResultPtr get(unsigned long timeout = LONG_MAX) = 0; + /** + * Adds the specified listener to this future. The specified listener is notified when this future is done. If this + * future is already completed, the specified listener will be notified immediately. + * + * @param listener FutureListener + */ virtual Future &addListener(FutureListenerPtr listener) = 0; + /** + * Returns the cause of the failed future + * + * @return the cause of the failure. {@code null} if succeeded or this future is not completed yet. + */ virtual std::exception &getThrowable() = 0; }; diff --git a/FutureListener.h b/FutureListener.h index 8ef7c28..ee52a28 100644 --- a/FutureListener.h +++ b/FutureListener.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_FUTURE_LISTENER_H #define OMS_FUTURE_LISTENER_H @@ -15,6 +31,10 @@ BEGIN_NAMESPACE_2(io, openmessaging) } + /** + * Invoked when the operation completes, be the associated {@link Promise} successful or not. + * @param future The associated promise facade + */ virtual void operationComplete(const Future& future) = 0; }; diff --git a/Headers.h b/Headers.h new file mode 100644 index 0000000..cda9f3d --- /dev/null +++ b/Headers.h @@ -0,0 +1,335 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OMS_HEADERS_H +#define OMS_HEADERS_H + +#include + +#include "smart_pointer.h" +#include "Namespace.h" +#include "Uncopyable.h" + +BEGIN_NAMESPACE_2(io, openmessaging) + + /** + * The {@code Message} interface is the root interface of all OMS messages, and the most commonly used OMS message is + * {@link BytesMessage}. + *

+ * Most message-oriented middleware (MOM) products treat messages as lightweight entities that consist of a header and a + * body, like Apache RocketMQ. The header part contains fields used for message + * routing and identification; the body part contains the application data to sent. + *

+ * The {@code Message} is a lightweight entity that only contains properties related to information of a specific message + * object, and the {@code Message} is composed of the following parts: + * + *

+ * + * The body part is deferred to the sub-classes of {@code Message}. + * + * @version OMS 1.0 + * @since OMS 1.0 + */ + class Headers : private Uncopyable { + public: + virtual ~Headers() { + + } + + /** + * The {@code DESTINATION} header field contains the destination to which the message is being sent. + *

+ * When a message is sent this value is set to the right {@code Queue}, then the message will be sent to the + * specified destination. + *

+ * When a message is received, its destination is equivalent to the {@code Queue} where the message resides in. + */ + virtual Headers &setDestination(const std::string &destination) = 0; + + /** + * The {@code MESSAGE_ID} header field contains a value that uniquely identifies each message sent by a {@code + * Producer}. + */ + virtual Headers &setMessageId(const std::string &messageId) = 0; + + /** + * The {@code BORN_TIMESTAMP} header field contains the time a message was handed off to a {@code Producer} to + * be sent. + *

+ * When a message is sent, BORN_TIMESTAMP will be set with current timestamp as the born timestamp of a message + * in client side, on return from the send method, the message's BORN_TIMESTAMP header field contains this + * value. + *

+ * When a message is received its, BORN_TIMESTAMP header field contains this same value. + *

+ * This filed is a {@code long} value, measured in milliseconds. + */ + virtual Headers &setBornTimestamp(long bornTimestamp) = 0; + + /** + * The {@code BORN_HOST} header field contains the born host info of a message in client side. + *

+ * When a message is sent, BORN_HOST will be set with the local host info, on return from the send method, the + * message's BORN_HOST header field contains this value. + *

+ * When a message is received, its BORN_HOST header field contains this same value. + */ + virtual Headers &setBornHost(const std::string &bornHost) = 0; + + /** + * The {@code STORE_TIMESTAMP} header field contains the store timestamp of a message in server side. + *

+ * When a message is sent, STORE_TIMESTAMP is ignored. + *

+ * When the send method returns it contains a server-assigned value. + *

+ * This filed is a {@code long} value, measured in milliseconds. + */ + virtual Headers &setStoreTimestamp(long storeTimestamp) = 0; + + /** + * The {@code STORE_HOST} header field contains the store host info of a message in server side. + *

+ * When a message is sent, STORE_HOST is ignored. + *

+ * When the send method returns it contains a server-assigned value. + */ + virtual Headers &setStoreHost(const std::string &storeHost) = 0; + + /** + * The {@code DELAY_TIME} header field contains a number that represents the delayed times in milliseconds. + *

+ * The message will be delivered after delayTime milliseconds starting from {@CODE BORN_TIMESTAMP} . When this + * filed isn't set explicitly, this means this message should be delivered immediately. + */ + virtual Headers &setDelayTime(long delayTime) = 0; + + /** + * The {@code EXPIRE_TIME} header field contains the expiration time, it represents a time-to-live value. + *

+ * The {@code EXPIRE_TIME} represents a relative valid interval that a message can be delivered in it. If the + * EXPIRE_TIME field is specified as zero, that indicates the message does not expire. + *

+ *

+ * When an undelivered message's expiration time is reached, the message should be destroyed. OMS does not + * define a notification of message expiration. + *

+ */ + virtual Headers &setExpireTime(long expireTime) = 0; + + /** + * The {@code PRIORITY} header field contains the priority level of a message, a message with a higher priority + * value should be delivered preferentially. + *

+ * OMS defines a ten level priority value with 1 as the lowest priority and 10 as the highest, and the default + * priority is 5. The priority beyond this region will be ignored. + *

+ * OMS does not require or provide any guarantee that the message should be delivered in priority order + * strictly, but the vendor should provide a best effort to deliver expedited messages ahead of normal + * messages. + *

+ * If PRIORITY field isn't set explicitly, use {@code 5} as the default priority. + */ + virtual Headers &setPriority(short priority) = 0; + + /** + * The {@code RELIABILITY} header field contains the reliability level of a message, the vendor should guarantee + * the reliability level for a message. + *

+ * OMS defines two modes of message delivery: + *

+ */ + virtual Headers &setDurability(short durability) = 0; + + /** + * The {@code messagekey} header field contains the custom key of a message. + *

+ * This key is a customer identifier for a class of messages, and this key may be used for server to hash or + * dispatch messages, or even can use this key to implement order message. + *

+ */ + virtual Headers &setMessageKey(const std::string &messageKey) = 0; + + /** + * The {@code TRACE_ID} header field contains the trace ID of a message, which represents a global and unique + * identification, to associate key events in the whole lifecycle of a message, like sent by who, stored at + * where, and received by who. + *

+ * And, the messaging system only plays exchange role in a distributed system in most cases, so the TraceID can + * be used to trace the whole call link with other parts in the whole system. + */ + virtual Headers &setTraceId(const std::string &traceId) = 0; + + /** + * The {@code DELIVERY_COUNT} header field contains a number, which represents the count of the message + * delivery. + */ + virtual Headers &setDeliveryCount(short deliveryCount) = 0; + + /** + * This field {@code TRANSACTION_ID} is used in transactional message, and it can be used to trace a + * transaction. + *

+ * So the same {@code TRANSACTION_ID} will be appeared not only in prepare message, but also in commit message, + * and consumer received message also contains this field. + */ + virtual Headers &setTransactionId(const std::string &transactionId) = 0; + + /** + * A client can use the {@code CORRELATION_ID} field to link one message with another. A typical use is to link + * a response message with its request message. + */ + virtual Headers &setCorrelationId(const std::string &scorrelationId) = 0; + + /** + * The field {@code COMPRESSION} in headers represents the message body compress algorithm. vendors are free to + * choose the compression algorithm, but must ensure that the decompressed message is delivered to the user. + */ + virtual Headers &setCompression(short compression) = 0; + + /** + * See {@link Headers#setDestination(String)} + * + * @return destination + */ + virtual std::string getDestination() = 0; + + /** + * See {@link Headers#setMessageId(String)} + * + * @return messageId + */ + virtual std::string getMessageId() = 0; + + /** + * See {@link Headers#setBornTimestamp(long)} + * + * @return bornTimestamp + */ + virtual long getBornTimestamp() = 0; + + /** + * See {@link Headers#setBornHost(String)} + * + * @return bornHost + */ + virtual std::string getBornHost() = 0; + + /** + * See {@link Headers#setStoreTimestamp(long)} + * + * @return storeTimestamp + */ + virtual long getStoreTimestamp() = 0; + + /** + * See {@link Headers#setStoreHost(String)} + * + * @return storeHost + */ + virtual std::string getStoreHost() = 0; + + /** + * See {@link Headers#setDelayTime(long)} + * + * @return delayTime + */ + virtual long getDelayTime() = 0; + + /** + * See {@link Headers#setExpireTime(long)} + * + * @return expireTime + */ + virtual long getExpireTime() = 0; + + /** + * See {@link Headers#setPriority(short)} + * + * @return priority + */ + virtual short getPriority() = 0; + + /** + * See {@link Headers#setDurability(short)} + * + * @return durability + */ + virtual short getDurability() = 0; + + /** + * See {@link Headers#setMessageKey(String)} + * + * @return messageKey + */ + virtual std::string getMessageKey() = 0; + + /** + * See {@link Headers#setTraceId(String)} + * + * @return traceId + */ + virtual std::string getTraceId() = 0; + + /** + * See {@link Headers#setDeliveryCount(int)} + * + * @return deliveryCount + */ + virtual short getDeliveryCount() = 0; + + /** + * See {@link Headers#setTransactionId(String)} + * + * @return transactionId + */ + virtual std::string getTransactionId() = 0; + + /** + * See {@link Headers#setCorrelationId(String)} + * + * @return correlationId + */ + virtual std::string getCorrelationId() = 0; + + /** + * See {@link Headers#setCompression(short)} + * + * @return compression + */ + virtual short getCompression() = 0; + + }; + + typedef NS::shared_ptr HeadersPtr; + +END_NAMESPACE_2(io, openmessaging) + +#endif // OMS_HEADERS_H diff --git a/KeyValue.h b/KeyValue.h index 73428b0..45cd252 100644 --- a/KeyValue.h +++ b/KeyValue.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_KEY_VALUE_H #define OMS_KEY_VALUE_H @@ -33,6 +49,8 @@ BEGIN_NAMESPACE_2(io, openmessaging) } + virtual KeyValue &put(const std::string &key, short value) = 0; + virtual KeyValue &put(const std::string &key, int value) = 0; virtual KeyValue &put(const std::string &key, long value) = 0; @@ -41,6 +59,8 @@ BEGIN_NAMESPACE_2(io, openmessaging) virtual KeyValue &put(const std::string &key, const std::string &value) = 0; + virtual short getShort(const std::string &key, short defaultValue = 0) = 0; + virtual int getInt(const std::string &key, int defaultValue = 0) = 0; virtual long getLong(const std::string &key, long defaultValue = 0L) = 0; diff --git a/Message.h b/Message.h index 1d5e587..1b9572f 100644 --- a/Message.h +++ b/Message.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_MESSAGE_H #define OMS_MESSAGE_H @@ -5,7 +21,7 @@ #include "smart_pointer.h" #include "KeyValue.h" -#include "BuiltinKeys.h" +#include "OMSBuiltinKeys.h" #include "Namespace.h" #include "Uncopyable.h" @@ -40,26 +56,8 @@ BEGIN_NAMESPACE_2(io, openmessaging) } - virtual KeyValuePtr sysHeaders() = 0; - - virtual KeyValuePtr userHeaders() = 0; - - virtual Message& putSysHeaders(const std::string &key, int value) = 0; - - virtual Message& putSysHeaders(const std::string &key, long value) = 0; - - virtual Message& putSysHeaders(const std::string &key, double value) = 0; - - virtual Message& putSysHeaders(const std::string &key, const std::string &value) = 0; - - virtual Message& putUserHeaders(const std::string &key, int value) = 0; - - virtual Message& putUserHeaders(const std::string &key, long value) = 0; - - virtual Message& putUserHeaders(const std::string &key, double value) = 0; - - virtual Message& putUserHeaders(const std::string &key, const std::string &value) = 0; - + virtual KeyValuePtr properties() = 0; + virtual HeadersPtr headers() = 0; }; typedef NS::shared_ptr MessagePtr; diff --git a/MessageFactory.h b/MessageFactory.h index 537e274..64b12c2 100644 --- a/MessageFactory.h +++ b/MessageFactory.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_MESSAGE_FACTORY_H #define OMS_MESSAGE_FACTORY_H @@ -29,7 +45,7 @@ BEGIN_NAMESPACE_2(io, openmessaging) * @return the created {@code BytesMessage} object * @throws OMSRuntimeException if the OMS provider fails to create this message due to some internal error. */ - virtual ByteMessagePtr createBytesMessage(const std::string &topic, const MessageBody &body) = 0; + virtual ByteMessagePtr createMessage(const std::string &queueName, const MessageBody &body) = 0; }; END_NAMESPACE_2(io, openmessaging) diff --git a/MessagingAccessPoint.h b/MessagingAccessPoint.h index 0c97795..988e326 100644 --- a/MessagingAccessPoint.h +++ b/MessagingAccessPoint.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_MESSAGING_ACCESS_POINT_H #define OMS_MESSAGING_ACCESS_POINT_H @@ -8,8 +24,7 @@ #include "producer/Producer.h" #include "consumer/PullConsumer.h" #include "consumer/PushConsumer.h" -#include "consumer/StreamingConsumer.h" -#include "ResourceManager.h" +#include "manager/ResourceManager.h" #include "observer/Observer.h" #include "Namespace.h" @@ -45,7 +60,7 @@ BEGIN_NAMESPACE_2(io, openmessaging) * @return the OMS version of implementation * @see OMS#specVersion */ - virtual std::string implVersion() = 0; + virtual std::string version() = 0; /** * Returns the attributes of this {@code MessagingAccessPoint} instance. @@ -71,7 +86,8 @@ BEGIN_NAMESPACE_2(io, openmessaging) * @throws OMSRuntimeException if the {@code MessagingAccessPoint} fails to handle this request * due to some internal error */ - virtual producer::ProducerPtr createProducer(const KeyValuePtr &properties = kv_nullptr) = 0; + virtual producer::ProducerPtr createProducer() = 0; + virtual producer::ProducerPtr createProducer(const TransactionStateCheckListenerPtr &transactionStateCheckListener) = 0; /** * Creates a new {@code PushConsumer} for the specified {@code MessagingAccessPoint}. @@ -82,25 +98,7 @@ BEGIN_NAMESPACE_2(io, openmessaging) * @throws OMSRuntimeException if the {@code MessagingAccessPoint} fails to handle this request * due to some internal error */ - virtual consumer::PushConsumerPtr createPushConsumer(const KeyValuePtr &properties = kv_nullptr) = 0; - - /** - * Creates a new {@code PullConsumer} for the specified {@code MessagingAccessPoint}. - * - * @return the created {@code PullConsumer} - * @throws OMSRuntimeException if the {@code MessagingAccessPoint} fails to handle this request - * due to some internal error - */ - virtual consumer::PullConsumerPtr createPullConsumer(const KeyValuePtr &properties = kv_nullptr) = 0; - - /** - * Creates a new {@code StreamingConsumer} for the specified {@code MessagingAccessPoint}. - * - * @return the created {@code Stream} - * @throws OMSRuntimeException if the {@code MessagingAccessPoint} fails to handle this request - * due to some internal error - */ - virtual consumer::StreamingConsumerPtr createStreamingConsumer(const KeyValuePtr &properties = kv_nullptr) = 0; + virtual consumer::PushConsumerPtr createConsumer() = 0; /** * Gets a lightweight {@code ResourceManager} instance from the specified {@code MessagingAccessPoint}. diff --git a/Namespace.h b/Namespace.h index a3de462..be863e9 100644 --- a/Namespace.h +++ b/Namespace.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_NAMESPACE_H #define OMS_NAMESPACE_H diff --git a/OMS.h b/OMS.h index 52063be..c70c929 100644 --- a/OMS.h +++ b/OMS.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_OMS_H #define OMS_OMS_H diff --git a/OMSBuiltinKeys.h b/OMSBuiltinKeys.h new file mode 100644 index 0000000..0240b20 --- /dev/null +++ b/OMSBuiltinKeys.h @@ -0,0 +1,32 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OMS_BUILTIN_KEYS_H +#define OMS_BUILTIN_KEYS_H + +#include +#include "Namespace.h" + +BEGIN_NAMESPACE_2(io, openmessaging) + + static const std::string DRIVER_IMPL = "DRIVER_IMPL"; + static const std::string ACCESS_POINTS = "ACCESS_POINTS"; + static const std::string ACCOUNT_ID = "ACCOUNT_ID"; + static const std::string REGION = "REGION"; + static const std::string OPERATION_TIMEOUT = "OPERATION_TIMEOUT"; + +END_NAMESPACE_2(io, openmessaging) +#endif // OMS_BUILTIN_KEYS_H diff --git a/OMSException.h b/OMSException.h deleted file mode 100644 index 23b9b52..0000000 --- a/OMSException.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef OMS_OMS_EXCEPTION_H -#define OMS_OMS_EXCEPTION_H - -#include -#include "Namespace.h" - -BEGIN_NAMESPACE_2(io, openmessaging) - - class OMSException { - public: - OMSException(const std::string &reason = "Unknown Reason") - : _reason(reason) { - - } - - const char *what() const { - return _reason.c_str(); - } - - private: - const std::string _reason; - }; - -END_NAMESPACE_2(io, openmessaging) -#endif //OMS_OMS_EXCEPTION_H diff --git a/OMSResponseStatus.h b/OMSResponseStatus.h new file mode 100644 index 0000000..4aafc64 --- /dev/null +++ b/OMSResponseStatus.h @@ -0,0 +1,53 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OMS_RESPONSE_STATUS_H +#define OMS_RESPONSE_STATUS_H +BEGIN_NAMESPACE_u2(io, openmessaging) +enum OMSResponceStatus{ + UnsupportedVersion = 1101, + Success = 1200, + BadRequest = 1400, + Unauthorized = 1401, + MessageBodyRequired = 1402, + Forbidden = 1403, + DestinationNotFound = 1404, + NamespaceNotFound = 1405, + DestinationAlreadyExists = 1406, + NamespaceAlreadyExists = 1407, + ConsumerIdAlreadyExists = 1408, + ProducerIdAlreadyExists = 1409, + RequestTimeout = 1410, + MessageAttributesTooLarge = 1411, + MessageHeaderTooLarge = 1412, + MessageBodyTooLarge = 1413, + NoNewMessageFound = 1414, + MaxTopicsReached = 1415, + MaxQueuesReached = 1416, + MaxNamespacesReached = 1417, + BadParameter = 1416, + ServerStatus = 1500, + StorageServiceStatus = 1501, + StorageServiceBusy = 1502, + ServiceNotAvailable = 1503, + FlushDiskTimeout = 1504, + CreateMessagingAccessPointFailed = 10000, + IllegalDriver = 10001, + IllegalVersion = 10002, + VersionNotCompatibleSpecification = 10003, +}; +END_NAMESPACE_2(io, openmessaging) +#endif //OMS_RESPONSE_STATUS_H diff --git a/OpenMessaging.h b/OpenMessaging.h index a01ea4c..c26604e 100644 --- a/OpenMessaging.h +++ b/OpenMessaging.h @@ -1,8 +1,24 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_OPEN_MESSAGING_H #define OMS_OPEN_MESSAGING_H #include "OMS.h" #include "MessagingAccessPoint.h" -#include "BuiltinKeys.h" +#include "OMSBuiltinKeys.h" #endif //OMS_OPEN_MESSAGING_H diff --git a/Promise.h b/Promise.h index 55cbea5..6f6dbf1 100644 --- a/Promise.h +++ b/Promise.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_PROMISE_H #define OMS_PROMISE_H diff --git a/README.md b/README.md index 26b93c4..ff3aa39 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,8 @@ [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/openmessaging/public) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) -### A vendor-neutral open standard for distributed messaging and streaming -OpenMessaging, which includes the establishment of industry guidelines and messaging, streaming specifications to provide a common framework for finance, e-commerce, IoT and big-data area. The design principles are the cloud-oriented, simplicity, flexibility, and language independent in distributed heterogeneous environments. Conformance to these specifications will make it possible to develop a heterogeneous messaging applications across all major platforms and operating systems. - -## The domain architecture -![domain-design](assets/images/OpenMessaging-V0.3.0-alpha.png) - -## Introduction -This repository contains Open Messaging Specification APIs in C++. An example implementation can be found [here](https://github.com/openmessaging/openmessaging-client-sdk-cpp). - C++ APIs are designed to be consistent with [Java APIs](https://openmessaging.github.io/openmessaging-java/) in terms of semantics. +Version: See [Java APIs](https://openmessaging.github.io/openmessaging-java/). ## ![Powered by Linux Foundation](http://openmessaging.cloud/images/linux-foundation-logo.png) \ No newline at end of file diff --git a/ResourceManager.h b/ResourceManager.h deleted file mode 100644 index 525cd20..0000000 --- a/ResourceManager.h +++ /dev/null @@ -1,205 +0,0 @@ -#ifndef OMS_RESOURCE_MANAGER_H -#define OMS_RESOURCE_MANAGER_H - -#include - -#include "smart_pointer.h" -#include "ServiceLifecycle.h" -#include "KeyValue.h" -#include "routing/Routing.h" -#include "Namespace.h" - -BEGIN_NAMESPACE_2(io, openmessaging) - - /** - * The {@code ResourceManager} is to provide a unified interface of resource management, - * allowing developers to manage the namespace, queue and routing resources. - *

- * Create, set, get and delete are the four basic operations of {@code ResourceManager}. - *

- * {@code ResourceManager} also supports fetching and updating resource attributes dynamically. - *

- * {@link MessagingAccessPoint#resourceManager()} ()} is the unique method to obtain a {@code ResourceManager} - * instance. Changes made through this instance will immediately apply to the message-oriented middleware (MOM) behind - * {@code MessagingAccessPoint}. - *

- * All operations conducted via this instance are confined to the configured namespace, - * with default namespace derived from the OMS driver url of {@code MessagingAccessPoint}.Change namespace - * by {@link ResourceManager#switchNamespace(String)} whenever necessary. - * - * @version OMS 1.0.0 - * @since OMS 1.0.0 - */ - class ResourceManager : public virtual Uncopyable { - public: - virtual ~ResourceManager() { - - } - - /** - * Creates a {@code Namespace} resource with some preset attributes. - * - * @param nsName the name of the new namespace - * @param attributes the preset attributes - */ - virtual void createNamespace(const std::string &ns, KeyValuePtr &attributes) = 0; - - /** - * Sets the attributes of the configured namespace, the old attributes will be replaced - * by the provided attributes, only the provided key will be updated. - * - * @param attributes the new attributes - * @throws OMSResourceNotExistException if the configured namespace does not exist - */ - virtual void setNamespaceAttributes(const KeyValuePtr &attributes) = 0; - - /** - * Gets the attributes of the configured namespace. - * - * @return the attributes of namespace - * @throws OMSResourceNotExistException if the configured namespace does not exist - */ - virtual KeyValuePtr getNamespaceAttributes() = 0; - - /** - * Deletes an existing namespace resource. - * - * @param ns the namespace to delete - * @throws OMSResourceNotExistException if the specified namespace does not exist - */ - virtual void deleteNamespace(const std::string &ns) = 0; - - /** - * Gets the namespace list in the current {@code MessagingAccessPoint}. - * - * @return the list of all namespaces - */ - virtual std::vector listNamespaces() = 0; - - /** - * Switches the default namespace to the new one, and all the operations will reflect to - * the new namespace after the method returns successfully. - * - * @param ns the target namespace to switch to - * @throws OMSResourceNotExistException if the new namespace does not exist - */ - virtual void switchNamespace(const std::string &ns) = 0; - - /** - * Creates a {@code Queue} resource in the configured namespace with some preset attributes. - * - * @param queueName the name of the new queue - * @param attributes the preset attributes - * @throws OMSResourceNotExistException if the specified queue name is duplicated - */ - virtual void createQueue(const std::string &ns, const std::string &queue, KeyValuePtr attributes) = 0; - - /** - * Sets the attributes of the specified queue, the old attributes will be replaced - * by the provided attributes, only the provided key will be updated. - * - * @param queueName the queue name - * @param attributes the new attributes - * @throws OMSResourceNotExistException if the specified queue does not exist - */ - virtual void setQueueAttributes(const std::string &ns, const std::string &queue, KeyValuePtr attributes) = 0; - - /** - * Gets the attributes of the specified queue. - * - * @param queueName the queue name - * @return the attributes of namespace - * @throws OMSResourceNotExistException if the specified queue or namespace does not exist - */ - virtual KeyValuePtr getQueueAttributes(const std::string &ns, const std::string &queue) = 0; - - /** - * Deletes an existing queue resource. - * - * @param queueName the queue needs to be deleted - * @throws OMSResourceNotExistException if the specified queue or namespace does not exist - */ - virtual void deleteQueue(const std::string &queue) = 0; - - /** - * Gets the queue list in the configured namespace. - * - * @return the list of all queues - */ - virtual std::vector listQueues() = 0; - - /** - * Creates a {@code Routing} resource in the configured namespace with some preset attributes. - * - * @param routingName the name of the new routing - * @param attributes the preset attributes - * @throws OMSResourceNotExistException if the configured namespace is not exists - */ - virtual void createRouting(const std::string &routingName, const KeyValuePtr &attributes) = 0; - - /** - * Sets the attributes of the specified routing, the old attributes will be replaced - * by the provided attributes, only the provided key will be updated. - * - * @param routingName the routing name - * @param attributes the new attributes - * @throws OMSResourceNotExistException if the specified routing or namespace is not exists - */ - virtual void setRoutingAttributes(const std::string &routingName, const KeyValuePtr &attributes) = 0; - - /** - * Gets the attributes of the specified routing. - * - * @param routingName the routing name - * @return the attributes of routing - * @throws OMSResourceNotExistException if the specified routing or namespace is not exists - */ - virtual KeyValuePtr getRoutingAttributes(const std::string &queueName) = 0; - - /** - * Deletes an existing routing resource. - * - * @param routingName the routing needs to be deleted - * @throws OMSResourceNotExistException if the specified routing or namespace is not exists - */ - virtual void deleteRouting(const std::string &ns, const std::string &route) = 0; - - /** - * Gets the routing list in the configured namespace. - * - * @return the list of all routings - * @throws OMSResourceNotExistException if the configured namespace is not exists - */ - virtual std::vector listRoutings(const std::string &ns) = 0; - - /** - * Gets the stream list behind the specified queue. - * - * @param queueName the queue name - * @return the list of all streams - */ - virtual std::vector listStreams(const std::string &queueName) = 0; - - /** - * Updates some system headers of a message in the configured namespace. - *

- * Below system headers are allowed to be changed dynamically: - *

    - *
  • {@link Message.BuiltinKeys#START_TIME}
  • - *
  • {@link Message.BuiltinKeys#STOP_TIME}
  • - *
  • {@link Message.BuiltinKeys#TIMEOUT}
  • - *
  • {@link Message.BuiltinKeys#PRIORITY}
  • - *
  • {@link Message.BuiltinKeys#SCHEDULE_EXPRESSION}
  • - *
- * - * @param messageId the id of message - * @param headers the new headers - */ - virtual void updateMessage(const std::string &messageId, KeyValuePtr &headers) = 0; - }; - - typedef NS::shared_ptr ResourceManagerPtr; - -END_NAMESPACE_2(io, openmessaging) - -#endif // OMS_RESOURCE_MANAGER_H diff --git a/ServiceLifecycle.h b/ServiceLifecycle.h index 840106c..bec9452 100644 --- a/ServiceLifecycle.h +++ b/ServiceLifecycle.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_SERVICE_LIFECYCLE_H #define OMS_SERVICE_LIFECYCLE_H diff --git a/Uncopyable.h b/Uncopyable.h index 4ac3e2c..57cc64a 100644 --- a/Uncopyable.h +++ b/Uncopyable.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_UNCOPYABLE_H #define OMS_UNCOPYABLE_H diff --git a/assets/images/OpenMessaging-V0.2.0-alpha.png b/assets/images/OpenMessaging-V0.2.0-alpha.png deleted file mode 100644 index c82b0336919828d6f4f84b531b42031da662505e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54064 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 diff --git a/assets/images/OpenMessaging-V0.3.0-alpha.png b/assets/images/OpenMessaging-V0.3.0-alpha.png deleted file mode 100644 index 368cf4f814b17285e1bed788b642289c5ab2007a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58165 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 diff --git a/assets/images/domain-design.png b/assets/images/domain-design.png deleted file mode 100644 index 19190e53a9b4a11a16f6e15bbe8b6b35c11d6add..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52377 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 rIq2dQwvJDu)fRC{glq_CFO%!-!^l^|s$>ZO7 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 + +#include "smart_pointer.h" +#include "ServiceLifecycle.h" +#include "MessageListener.h" +#include "Namespace.h" +#include "OMS.h" +#include "interceptor/ConsumerInterceptor.h" + +BEGIN_NAMESPACE_3(io, openmessaging, consumer) + /** + * A {@code Consumer} object to receive messages from multiple queues, these messages are pushed from + * MOM server to {@code Consumer} client. + * + * @version OMS 1.0 + * @see MessagingAccessPoint#createConsumer() + * @since OMS 1.0 + */ + class Consumer : public virtual ServiceLifecycle { + public: + virtual ~Consumer() { + + } + + + /** + * Resumes the {@code Consumer} after a suspend. + *

+ * This method resumes the {@code Consumer} instance after it was suspended. + * The instance will not receive new messages between the suspend and resume calls. + * + * @see Consumer#suspend() + */ + virtual void resume() = 0; + + /** + * Suspends the {@code Consumer} for later resumption. + *

+ * This method suspends the consumer until it is resumed. + * The consumer will not receive new messages between the suspend and resume calls. + *

+ * This method behaves exactly as if it simply performs the call {@code suspend(0)}. + * + * @see Consumer#resume() + */ + virtual void suspend(long timeout = 0) = 0; + + /** + * This method is used to find out whether the {@code Consumer} is suspended. + * + * @return true if this {@code Consumer} is suspended, false otherwise + */ + virtual bool isSuspended() = 0; + + /** + * Binds the {@code Consumer} to a specified queue, with a {@code MessageListener}. + *

+ * {@link MessageListener#onReceived(Message, MessageListener.Context)} will be called when new + * delivered message is coming. + * + * @param queueName a specified queue + * @param listener a specified listener to receive new message + * @return this {@code Consumer} instance + */ + virtual Consumer &bindQueue(const std::string &queueName, + const MessageListenerPtr &listener) = 0; + + /** + * Unbinds the {@code Consumer} from a specified queue. + *

+ * After the success call, this consumer won't receive new message + * from the specified queue any more. + * + * @param queueName a specified queue + * @return this {@code Consumer} instance + */ + virtual Consumer &unbindQueue(const std::string &queueName) = 0; + + /** + * Adds a {@code ConsumerInterceptor} instance to this consumer. + * + * @param interceptor an interceptor instance + */ + virtual void addInterceptor(const interceptor::ConsumerInterceptorPtr &interceptor) = 0; + + /** + * Removes an interceptor from this consumer. + * + * @param interceptor an interceptor to be removed + */ + virtual void removeInterceptor(const interceptor::ConsumerInterceptorPtr &interceptor) = 0; + + /** + * Receives the next message from the bind queues of this consumer in pull model. + *

+ * This call blocks indefinitely until a message is arrives, the timeout expires, or until this {@code PullConsumer} + * is shut down. + * + * @param timeout receive message will blocked at most timeout milliseconds. + * @return the next message received from the bind queues, or null if the consumer is concurrently shut down. + */ + virtual MessagePtr &receive(long timeout) = 0; + + /** + * Acknowledges the specified and consumed message with the unique message receipt handle, in the scenario of using + * manual commit. + *

+ * Messages that have been received but not acknowledged may be redelivered. + * + * @param receiptHandle the receipt handle associated with the consumed message. + */ + virtual void ack(String receiptHandle) = 0; + }; + + typedef NS::shared_ptr ConsumerPtr; + +END_NAMESPACE_3(io, openmessaging, consumer) + +#endif //OMS_CONSUMER_H diff --git a/consumer/Context.h b/consumer/Context.h index bbf56e8..c50dc22 100644 --- a/consumer/Context.h +++ b/consumer/Context.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_CONTEXT_H #define OMS_CONTEXT_H @@ -12,8 +28,11 @@ BEGIN_NAMESPACE_3(io, openmessaging, consumer) virtual ~Context() { } - virtual KeyValuePtr attributes() = 0; - + /** + * Acknowledges the specified and consumed message, which is related to this {@code Context}. + *

+ * Messages that have been received but not acknowledged may be redelivered. + */ virtual void ack() = 0; }; diff --git a/consumer/MessageListener.h b/consumer/MessageListener.h index 231fcc7..acc3258 100644 --- a/consumer/MessageListener.h +++ b/consumer/MessageListener.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_MESSAGE_LISTENER_H #define OMS_MESSAGE_LISTENER_H @@ -22,7 +38,15 @@ BEGIN_NAMESPACE_3(io, openmessaging, consumer) } - virtual void onMessage(MessagePtr &message, ContextPtr &context) = 0; + /** + * Callback method to receive incoming messages. + *

+ * A message listener should handle different types of {@code Message}. + * + * @param message the received message object. + * @param context the context delivered to the consume thread. + */ + virtual void onReceived(MessagePtr &message, ContextPtr &context) = 0; }; typedef NS::shared_ptr MessageListenerPtr; diff --git a/consumer/PullConsumer.h b/consumer/PullConsumer.h deleted file mode 100644 index acfcb8e..0000000 --- a/consumer/PullConsumer.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef OMS_PULL_CONSUMER_H -#define OMS_PULL_CONSUMER_H - -#include - -#include "smart_pointer.h" -#include "KeyValue.h" -#include "ServiceLifecycle.h" -#include "Namespace.h" -#include "Message.h" -#include "OMS.h" - -BEGIN_NAMESPACE_3(io, openmessaging, consumer) - - /** - * A {@code PullConsumer} object can poll messages from the specified queue, - * and supports submit the consume result by acknowledgement. - * - * @version OMS 1.0 - * @see MessagingAccessPoint#createPullConsumer(String) - * @since OMS 1.0 - */ - class PullConsumer : public virtual ServiceLifecycle { - public: - virtual ~PullConsumer() { - - } - - /** - * Returns the attributes of this {@code PullConsumer} instance. - * Changes to the return {@code KeyValue} are not reflected in physical {@code PullConsumer}. - *

- * There are some standard attributes defined by OMS for {@code PullConsumer}: - *

    - *
  • {@link OMSBuiltinKeys#CONSUMER_ID}, the unique consumer id for a consumer instance. - *
  • {@link OMSBuiltinKeys#OPERATION_TIMEOUT}, the default timeout period for operations of {@code PullConsumer}. - *
- * - * @return the attributes - */ - virtual KeyValuePtr attributes() = 0; - - /** - * Attaches the {@code PullConsumer} to a specified queue. - * - * @param queueName a specified queue - * @return this {@code PullConsumer} instance - */ - virtual PullConsumer& attachQueue(const std::string &queueName, const KeyValuePtr &properties = kv_nullptr) = 0; - - /** - * Detaches the {@code PullConsumer} from a specified queue. - *

- * After the success call, this consumer won't receive new message - * from the specified queue any more. - * - * @param queueName a specified queue - * @return this {@code PullConsumer} instance - */ - virtual PullConsumer& detachQueue(const std::string &queueName) = 0; - - /** - * Receives the next message from the attached queues of this consumer. - *

- * This call blocks indefinitely until a message is arrives, the timeout expires, - * or until this {@code PullConsumer} is shut down. - * - * @return the next message received from the attached queues, or null if the consumer is - * concurrently shut down or the timeout expires - * @throws OMSRuntimeException if the consumer fails to pull the next message due to some internal error. - */ - virtual MessagePtr receive(const KeyValuePtr &props = kv_nullptr) = 0; - - /** - * Acknowledges the specified and consumed message with the specified attributes. - *

- * Messages that have been received but not acknowledged may be redelivered. - * - * @param messageId the consumed message id - * @throws OMSRuntimeException if the consumer fails to acknowledge the messages due to some internal error. - */ - virtual void ack(const std::string &messageId, - const KeyValuePtr &props = kv_nullptr) = 0; - }; - - typedef NS::shared_ptr PullConsumerPtr; - - -END_NAMESPACE_3(io, openmessaging, consumer) - -#endif //OMS_PULL_CONSUMER_H diff --git a/consumer/PushConsumer.h b/consumer/PushConsumer.h deleted file mode 100644 index 30ebdeb..0000000 --- a/consumer/PushConsumer.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef OMS_PUSH_CONSUMER_H -#define OMS_PUSH_CONSUMER_H - -#include - -#include "smart_pointer.h" -#include "ServiceLifecycle.h" -#include "MessageListener.h" -#include "Namespace.h" -#include "OMS.h" -#include "interceptor/ConsumerInterceptor.h" - -BEGIN_NAMESPACE_3(io, openmessaging, consumer) - /** - * A {@code PushConsumer} object to receive messages from multiple queues, these messages are pushed from - * MOM server to {@code PushConsumer} client. - * - * @version OMS 1.0 - * @see MessagingAccessPoint#createPushConsumer() - * @since OMS 1.0 - */ - class PushConsumer : public virtual ServiceLifecycle { - public: - virtual ~PushConsumer() { - - } - - /** - * Returns the attributes of this {@code PushConsumer} instance. - * Changes to the return {@code KeyValue} are not reflected in physical {@code PushConsumer}. - *

- * There are some standard attributes defined by OMS for {@code PushConsumer}: - *

    - *
  • {@link OMSBuiltinKeys#CONSUMER_ID}, the unique consumer id for a consumer instance. - *
  • {@link OMSBuiltinKeys#OPERATION_TIMEOUT}, the default timeout period for operations of {@code PushConsumer}. - *
- * - * @return the attributes - */ - virtual KeyValuePtr attributes() = 0; - - /** - * Resumes the {@code PushConsumer} after a suspend. - *

- * This method resumes the {@code PushConsumer} instance after it was suspended. - * The instance will not receive new messages between the suspend and resume calls. - * - * @throws OMSRuntimeException if the instance has not been suspended. - * @see PushConsumer#suspend() - */ - virtual void resume() = 0; - - /** - * Suspends the {@code PushConsumer} for later resumption. - *

- * This method suspends the consumer until it is resumed. - * The consumer will not receive new messages between the suspend and resume calls. - *

- * This method behaves exactly as if it simply performs the call {@code suspend(0)}. - * - * @throws OMSRuntimeException if the instance is not currently running. - * @see PushConsumer#resume() - */ - virtual void suspend(long timeout = 0) = 0; - - /** - * This method is used to find out whether the {@code PushConsumer} is suspended. - * - * @return true if this {@code PushConsumer} is suspended, false otherwise - */ - virtual bool isSuspended() = 0; - - /** - * Attaches the {@code PushConsumer} to a specified queue, with a {@code MessageListener}. - *

- * {@link MessageListener#onReceived(Message, MessageListener.Context)} will be called when new - * delivered message is coming. - * - * @param queueName a specified queue - * @param listener a specified listener to receive new message - * @return this {@code PushConsumer} instance - */ - virtual PushConsumer &attachQueue(const std::string &queueName, - const MessageListenerPtr &listener, - const KeyValuePtr &properties = kv_nullptr) = 0; - - /** - * Detaches the {@code PushConsumer} from a specified queue. - *

- * After the success call, this consumer won't receive new message - * from the specified queue any more. - * - * @param queueName a specified queue - * @return this {@code PushConsumer} instance - */ - virtual PushConsumer &detachQueue(const std::string &queueName) = 0; - - /** - * Adds a {@code PushConsumerInterceptor} instance to this consumer. - * - * @param interceptor an interceptor instance - */ - virtual void addInterceptor(const interceptor::ConsumerInterceptorPtr &interceptor) = 0; - - /** - * Removes an interceptor from this consumer. - * - * @param interceptor an interceptor to be removed - */ - virtual void removeInterceptor(const interceptor::ConsumerInterceptorPtr &interceptor) = 0; - }; - - typedef NS::shared_ptr PushConsumerPtr; - -END_NAMESPACE_3(io, openmessaging, consumer) - -#endif //OMS_PUSH_CONSUMER_H diff --git a/consumer/StreamingConsumer.h b/consumer/StreamingConsumer.h deleted file mode 100644 index f2cf573..0000000 --- a/consumer/StreamingConsumer.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef OMS_STREAM_CONSUMER_H -#define OMS_STREAM_CONSUMER_H - -#include -#include - -#include "smart_pointer.h" -#include "KeyValue.h" -#include "ServiceLifecycle.h" -#include "StreamingIterator.h" -#include "Namespace.h" - -BEGIN_NAMESPACE_3(io, openmessaging, consumer) - /** - * A {@code Queue} is divided by many streams. - *

- * A {@code StreamingConsumer} object supports consume messages from a - * specified partition like a iterator. - * - * @version OMS 1.0 - * @see Stream - * @since OMS 1.0 - */ - class StreamingConsumer : public virtual ServiceLifecycle { - public: - virtual ~StreamingConsumer() { - - } - - virtual KeyValuePtr attributes() = 0; - - virtual StreamingIteratorPtr seek(const std::string &name, long offset, int whence) = 0; - - }; - typedef NS::shared_ptr StreamingConsumerPtr; - -END_NAMESPACE_3(io, openmessaging, consumer) - -#endif //OMS_STREAM_CONSUMER_H diff --git a/consumer/StreamingIterator.h b/consumer/StreamingIterator.h deleted file mode 100644 index 020b33c..0000000 --- a/consumer/StreamingIterator.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef OMS_STREAMING_ITERATOR_H -#define OMS_STREAMING_ITERATOR_H - - -#include "smart_pointer.h" -#include "ServiceLifecycle.h" -#include "Namespace.h" -#include "Message.h" - -BEGIN_NAMESPACE_3(io, openmessaging, consumer) - - class StreamingIterator : public virtual ServiceLifecycle { - public: - virtual ~StreamingIterator() { - - } - - virtual KeyValuePtr attributes() = 0; - - virtual void commit(bool flush) = 0; - - virtual bool hasNext() = 0; - - virtual MessagePtr next() = 0; - - virtual bool hasPrevious() = 0; - - virtual MessagePtr previous() = 0; - }; - - typedef NS::shared_ptr StreamingIteratorPtr; - -END_NAMESPACE_3(io, openmessaging, consumer) - -#endif //OMS_STREAMING_ITERATOR_H diff --git a/interceptor/ConsumerInterceptor.h b/interceptor/ConsumerInterceptor.h index d1cda89..1f7d13a 100644 --- a/interceptor/ConsumerInterceptor.h +++ b/interceptor/ConsumerInterceptor.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_CONSUMER_INTERCEPTOR_H #define OMS_CONSUMER_INTERCEPTOR_H @@ -9,7 +25,7 @@ BEGIN_NAMESPACE_3(io, openmessaging, interceptor) /** - * A {@code PushConsumerInterceptor} is used to intercept consume operations of push consumer. + * A {@code ConsumerInterceptor} is used to intercept consume operations of consumer. * * @version OMS 1.0 * @since OMS 1.0 @@ -21,10 +37,21 @@ BEGIN_NAMESPACE_3(io, openmessaging, interceptor) } virtual std::string name() const = 0; - - virtual void preReceive(const MessagePtr &message, const KeyValuePtr &attributes = kv_nullptr) = 0; - - virtual void postReceive(const MessagePtr &message, const KeyValuePtr &attributes = kv_nullptr) = 0; + /** + * Invoked before the invocation of {@link MessageListener#onReceived(Message, Context)}. + * + * @param message the message is actually received. + * @param attributes the extensible attributes delivered to the intercept thread. + */ + virtual void preReceive(const MessagePtr &message, const InterceptorContextPtr &attributes = kv_nullptr) = 0; + + /** + * Invoked after the invocation of {@link MessageListener#onReceived(Message, MessageListener.Context)}. + * + * @param message the message is actually received. + * @param attributes the extensible attributes delivered to the intercept thread. + */ + virtual void postReceive(const MessagePtr &message, const InterceptorContextPtr &attributes = kv_nullptr) = 0; }; typedef NS::shared_ptr ConsumerInterceptorPtr; diff --git a/interceptor/InterceptorContext.h b/interceptor/InterceptorContext.h new file mode 100644 index 0000000..a5da8fb --- /dev/null +++ b/interceptor/InterceptorContext.h @@ -0,0 +1,42 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OMS_INTERCEPTOR_CONTEXT_H +#define OMS_INTERCEPTOR_CONTEXT_H + +#include "Namespace.h" +#include "OMS.h" +#include "Uncopyable.h" + +BEGIN_NAMESPACE_3(io, openmessaging, interceptor) + + class InterceptorContext : private Uncopyable { + public: + virtual ~InterceptorContext() { + } + /** + * Returns the attributes of this {@code InterceptorContext} instance. + * + * @return the attributes. + */ + virtual KeyValuePtr attributes() = 0; + + }; + + typedef NS::shared_ptr InterceptorContextPtr; + +END_NAMESPACE_3(io, openmessaging, interceptor) +#endif //OMS_INTERCEPTOR_CONTEXT_H diff --git a/interceptor/ProducerInterceptor.h b/interceptor/ProducerInterceptor.h index f30cdfe..41058e4 100644 --- a/interceptor/ProducerInterceptor.h +++ b/interceptor/ProducerInterceptor.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_PRODUCER_INTERCEPTOR_H #define OMS_PRODUCER_INTERCEPTOR_H @@ -22,9 +38,23 @@ BEGIN_NAMESPACE_3(io, openmessaging, interceptor) virtual std::string name() const = 0; - virtual void preSend(const MessagePtr &message, const KeyValuePtr &attributes = kv_nullptr) = 0; + /** + * Invoked before the message is actually sent to the network. + *

+ * This allows for modification of the message if necessary. + * + * @param message a message will be sent. + * @param attributes the extensible attributes delivered to the intercept thread. + */ + virtual void preSend(const MessagePtr &message, const InterceptorContextPtr &context = kv_nullptr) = 0; - virtual void postSend(const MessagePtr &message, const KeyValuePtr &attributes = kv_nullptr) = 0; + /** + * Invoked immediately after the successful send invocation. + * + * @param message the message is actually sent. + * @param attributes the extensible attributes delivered to the intercept thread. + */ + virtual void postSend(const MessagePtr &message, const InterceptorContextPtr &context = kv_nullptr) = 0; }; typedef NS::shared_ptr ProducerInterceptorPtr; diff --git a/manager/ResourceManager.h b/manager/ResourceManager.h new file mode 100644 index 0000000..8f42cbf --- /dev/null +++ b/manager/ResourceManager.h @@ -0,0 +1,130 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OMS_RESOURCE_MANAGER_H +#define OMS_RESOURCE_MANAGER_H + +#include + +#include "../smart_pointer.h" +#include "../ServiceLifecycle.h" +#include "../KeyValue.h" +#include "../routing/Routing.h" +#include "../Namespace.h" + +BEGIN_NAMESPACE_3(io, openmessaging, manager) + + /** + * The {@code ResourceManager} is to provide a unified interface of resource management, + * allowing developers to manage the namespace, queue and routing resources. + *

+ * Create, set, get and delete are the four basic operations of {@code ResourceManager}. + *

+ * {@code ResourceManager} also supports fetching and updating resource attributes dynamically. + *

+ * {@link MessagingAccessPoint#resourceManager()} ()} is the unique method to obtain a {@code ResourceManager} + * instance. Changes made through this instance will immediately apply to the message-oriented middleware (MOM) behind + * {@code MessagingAccessPoint}. + *

+ * All operations conducted via this instance are confined to the configured namespace, + * with default namespace derived from the OMS driver url of {@code MessagingAccessPoint}.Change namespace + * by {@link ResourceManager#switchNamespace(String)} whenever necessary. + * + * @version OMS 1.0.0 + * @since OMS 1.0.0 + */ + class ResourceManager : public virtual Uncopyable { + public: + virtual ~ResourceManager() { + + } + + /** + * Creates a {@code Namespace} resource with some preset attributes. + * + * @param ns the name of the new namespace + */ + virtual void createNamespace(const std::string &ns) = 0; + + /** + * Deletes an existing namespace resource. + * + * @param ns the namespace to delete + */ + virtual void deleteNamespace(const std::string &ns) = 0; + + /** + * Gets the namespace list in the current {@code MessagingAccessPoint}. + * + * @return the list of all namespaces + */ + virtual std::vector listNamespaces() = 0; + + /** + * Switches the default namespace to the new one, and all the operations will reflect to + * the new namespace after the method returns successfully. + * + * @param ns the target namespace to switch to + */ + virtual void switchNamespace(const std::string &ns) = 0; + + /** + * Creates a {@code Queue} resource in the configured namespace with some preset attributes. + * + * @param queueName the name of the new queue + * @param attributes the preset attributes + */ + virtual void createQueue(const std::string &ns, const std::string &queue, KeyValuePtr attributes) = 0; + + /** + * Deletes an existing queue resource. + * + * @param queueName the queue needs to be deleted + */ + virtual void deleteQueue(const std::string &queue) = 0; + + /** + * Gets the queue list in the configured namespace. + * + * @return the list of all queues + */ + virtual std::vector listQueues() = 0; + + /** + * Routing from sourceQueue to targetQueue. Both queues are could be received messages after creating route action. + * + * @param sourceQueue source queue, process messages received from producer and duplicate those to target queue. + * @param targetQueue receive messages from source queue. + */ + virtual void routing(const std::string &sourceQueue, const std::string &targetQueue) = 0; + + /** + * In order to enable consumers to get the message in the specified mode, the filter rule follows the sql standard + * to filter out messages. + * + * @param queueName queue name. + * @param filterString SQL expression to filter out messages. + */ + virtual void filter(const std::string &queue, const std::string &filter) = 0; + + + }; + + typedef NS::shared_ptr ResourceManagerPtr; + +END_NAMESPACE_3(io, openmessaging, manager) + +#endif // OMS_RESOURCE_MANAGER_H diff --git a/observer/OMSEvent.h b/observer/OMSEvent.h deleted file mode 100644 index 71c1d81..0000000 --- a/observer/OMSEvent.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef OMS_OMS_EVENT_H -#define OMS_OMS_EVENT_H - -#include "Namespace.h" -#include "Uncopyable.h" - -BEGIN_NAMESPACE_3(io, openmessaging, observer) - - /** - * Observable objects can trigger a {@code OMSEvent}, which will be handled in {@link Observer#onEvent(OMSEvent)} - * - * @version OMS 1.0 - * @since OMS 1.0 - */ - class OMSEvent : private Uncopyable { - public: - virtual ~OMSEvent() { - - } - - virtual std::string type() = 0; - - virtual std::string details() = 0; - }; - - typedef NS::shared_ptr OMSEventPtr; - -END_NAMESPACE_3(io, openmessaging, observer) -#endif //OMS_OMS_EVENT_H diff --git a/observer/OMSExceptionEvent.h b/observer/OMSExceptionEvent.h deleted file mode 100644 index 4850e65..0000000 --- a/observer/OMSExceptionEvent.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef OMS_OMS_EXCEPTION_EVENT_H -#define OMS_OMS_EXCEPTION_EVENT_H - -#include "OMSEvent.h" -#include "Namespace.h" -BEGIN_NAMESPACE_3(io, openmessaging, observer) - - /** - * Special {@link OMSEvent} which is abnormal. - * - * @version OMS 1.0 - * @since OMS 1.0 - */ - class OMSExceptionEvent : public virtual OMSEvent { - public: - virtual ~OMSExceptionEvent() { - - } - }; - -END_NAMESPACE_3(io, openmessaging, observer) -#endif //OMS_OMS_EXCEPTION_EVENT_H diff --git a/observer/Observer.h b/observer/Observer.h deleted file mode 100644 index e21749f..0000000 --- a/observer/Observer.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef OMS_OBSERVER_H -#define OMS_OBSERVER_H - -#include "smart_pointer.h" -#include "OMSEvent.h" -#include "Namespace.h" -#include "Uncopyable.h" - -BEGIN_NAMESPACE_3(io, openmessaging, observer) - - /** - * A {@code Observer} interface is used to observe the {@code OMSEvent} - * dispatches in observable objects, like {@link MessagingAccessPoint} - * - * @version OMS 1.0 - * @since OMS 1.0 - */ - class Observer : private Uncopyable { - public: - virtual ~Observer() { - - } - - virtual void onEvent(const OMSEvent &event) = 0; - }; - - typedef NS::shared_ptr ObserverPtr; - -END_NAMESPACE_3(io, openmessaging, observer) - -#endif //OMS_OBSERVER_H diff --git a/producer/BatchMessageSender.h b/producer/BatchMessageSender.h deleted file mode 100644 index 139ec83..0000000 --- a/producer/BatchMessageSender.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef OMS_BATCHMESSAGESENDER_H -#define OMS_BATCHMESSAGESENDER_H - -#include "Namespace.h" -#include "Message.h" -#include "Uncopyable.h" - -BEGIN_NAMESPACE_3(io, openmessaging, producer) - /** - * A message sender created through {@link Producer#createSequenceBatchMessageSender()}, to send - * messages in batch way, and commit or roll back at the appropriate time. - * - * @version OMS 1.0 - * @since OMS 1.0 - */ - class BatchMessageSender : private Uncopyable { - public: - virtual ~BatchMessageSender() { - - } - - virtual BatchMessageSender& send(MessagePtr &message) = 0; - - virtual void commit() = 0; - - virtual void rollback() = 0; - - virtual void close() = 0; - }; - - typedef NS::shared_ptr BatchMessageSenderPtr; - -END_NAMESPACE_3(io, openmessaging, producer) - -#endif //OMS_BATCHMESSAGESENDER_H diff --git a/producer/CheckContext.h b/producer/CheckContext.h index 17fbde6..5676180 100644 --- a/producer/CheckContext.h +++ b/producer/CheckContext.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_CHECK_CONTEXT_H #define OMS_CHECK_CONTEXT_H @@ -11,10 +27,18 @@ BEGIN_NAMESPACE_3(io, openmessaging, producer) virtual ~CheckContext() { } - + /** + * Commits a transaction. + */ virtual void commit() = 0; - + /** + * Rolls back a transaction. + */ virtual void rollback() = 0; + /** + * Unknown transaction status, may be this transaction still on going. + */ + virtual void unknown() = 0; }; diff --git a/producer/ExecutionContext.h b/producer/ExecutionContext.h deleted file mode 100644 index 02d344b..0000000 --- a/producer/ExecutionContext.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef OMS_EXECUTION_CONTEXT_H -#define OMS_EXECUTION_CONTEXT_H - -#include "Namespace.h" -#include "Uncopyable.h" - -BEGIN_NAMESPACE_3(io, openmessaging, producer) - - class ExecutionContext : private Uncopyable { - public: - virtual ~ExecutionContext() { - - } - - virtual void commit() = 0; - - virtual void rollback() = 0; - - }; - - typedef NS::shared_ptr ExecutionContextPtr; - -END_NAMESPACE_3(io, openmessaging, producer) - -#endif //OMS_EXECUTION_CONTEXT_H diff --git a/producer/LocalTransactionExecutor.h b/producer/LocalTransactionExecutor.h deleted file mode 100644 index 67afac0..0000000 --- a/producer/LocalTransactionExecutor.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef OMS_LOCAL_TRANSACTION_EXECUTOR_H -#define OMS_LOCAL_TRANSACTION_EXECUTOR_H - -#include "Namespace.h" -#include "Message.h" -#include "producer/ExecutionContext.h" -#include "producer/CheckContext.h" -#include "Uncopyable.h" - -BEGIN_NAMESPACE_3(io, openmessaging, producer) - - /** - * Each executor will be associated with a transactional message, can be used to execute local transaction - * branch and submit the transaction status(commit or rollback). - *

- * - * The associated message will be exposed to consumer when the local transaction has been committed, or be - * discarded if local transaction has been rolled back. - * - *

- * If the executor don't submit the transaction status for a long time, the server may lookup it forwardly through - * {@link LocalTransactionBranchExecutor#checkLocalTransactionBranch(Message, CheckLocalTransactionBranchContext)} - * - * @version OMS 1.0 - * @since OMS 1.0 - */ - class LocalTransactionExecutor : private Uncopyable { - public: - virtual ~LocalTransactionExecutor() { - - } - - virtual void execute(const MessagePtr &message, const ExecutionContextPtr &context) = 0; - - virtual void check(const MessagePtr &message, const CheckContextPtr &context) = 0; - - }; - - typedef NS::shared_ptr LocalTransactionExecutorPtr; - -END_NAMESPACE_3(io, openmessaging, producer) - -#endif //OMS_LOCAL_TRANSACTION_EXECUTOR_H diff --git a/producer/Producer.h b/producer/Producer.h index abe9ce0..6bc3c27 100644 --- a/producer/Producer.h +++ b/producer/Producer.h @@ -1,16 +1,33 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_PRODUCER_H #define OMS_PRODUCER_H +#include #include "smart_pointer.h" #include "MessageFactory.h" #include "ServiceLifecycle.h" #include "Message.h" #include "SendResult.h" +#include "TransactionalSendResult.h" #include "Namespace.h" #include "OMS.h" -#include "LocalTransactionExecutor.h" +#include "TransactionStateCheckListener.h" #include "Future.h" -#include "BatchMessageSender.h" #include "interceptor/ProducerInterceptor.h" BEGIN_NAMESPACE_3(io, openmessaging, producer) @@ -43,51 +60,15 @@ BEGIN_NAMESPACE_3(io, openmessaging, producer) } - /** - * Returns the attributes of this {@code Producer} instance. - * Changes to the return {@code KeyValue} are not reflected in physical {@code Producer}. - *

- * There are some standard attributes defined by OMS for {@code Producer}: - *

    - *
  • {@link OMSBuiltinKeys#PRODUCER_ID}, the unique producer id for a producer instance. - *
  • {@link OMSBuiltinKeys#OPERATION_TIMEOUT}, the default timeout period for operations of {@code Producer}. - *
- * - * @return the attributes - */ - virtual KeyValuePtr attributes() = 0; - /** * Sends a message to the specified destination synchronously, the destination should be preset to - * {@link Message#sysHeaders()}, other header fields as well. + * {@link Message#Headers()}, other header fields as well. * * @param message a message will be sent * @return the successful {@code SendResult} - * @throws OMSMessageFormatException if an invalid message is specified. - * @throws OMSTimeOutException if the given timeout elapses before the send operation completes - * @throws OMSRuntimeException if the {@code Producer} fails to send the message due to some internal error. */ - virtual SendResultPtr send(const MessagePtr &message, - const KeyValuePtr &properties = kv_nullptr) = 0; + virtual SendResultPtr send(const MessagePtr &message) = 0; - /** - * Sends a transactional message to the specified destination synchronously, using the specified attributes, - * the destination should be preset to {@link Message#sysHeaders()}, other header fields as well. - *

- * A transactional message will be exposed to consumer if and only if the local transaction - * branch has been committed, or be discarded if local transaction has been rolled back. - * - * @param message a transactional message will be sent - * @param branchExecutor local transaction executor associated with the message - * @param attributes the specified attributes - * @return the successful {@code SendResult} - * @throws OMSMessageFormatException if an invalid message is specified. - * @throws OMSTimeOutException if the given timeout elapses before the send operation completes - * @throws OMSRuntimeException if the {@code Producer} fails to send the message due to some internal error. - */ - virtual SendResultPtr send(const MessagePtr &message, - const LocalTransactionExecutorPtr &executor, - const KeyValuePtr &properties) = 0; /** * Asynchronously send a message to its destination, which is specified in system headers. @@ -100,7 +81,7 @@ BEGIN_NAMESPACE_3(io, openmessaging, producer) * @param properties Optional additional properties. * @return Smart pointer to Future instance. */ - virtual FuturePtr sendAsync(const MessagePtr &message, const KeyValuePtr &properties = kv_nullptr) = 0; + virtual FuturePtr sendAsync(const MessagePtr &message) = 0; /** * Sends a message to the specified destination in one way, using the specified attributes, the destination @@ -112,14 +93,14 @@ BEGIN_NAMESPACE_3(io, openmessaging, producer) * @param message a message will be sent * @param properties the specified userHeaders */ - virtual void sendOneway(const MessagePtr &message, const KeyValuePtr &properties = kv_nullptr) = 0; + virtual void sendOneway(const MessagePtr &message) = 0; /** * Creates a {@code BatchMessageSender} to send message in batch way. * * @return a {@code BatchMessageSender} instance */ - virtual BatchMessageSenderPtr createSequenceBatchMessageSender() = 0; + virtual SendResultPtr send(const list &message) = 0; /** * Adds a {@code ProducerInterceptor} to intercept send operations of producer. @@ -134,6 +115,8 @@ BEGIN_NAMESPACE_3(io, openmessaging, producer) * @param interceptor a producer interceptor will be removed */ virtual void removeInterceptor(const interceptor::ProducerInterceptorPtr &interceptor) = 0; + + TransactionalResultPtr prepare(const MessagePtr &message) = 0; }; typedef NS::shared_ptr ProducerPtr; diff --git a/producer/SendResult.h b/producer/SendResult.h index ad2bf15..4ce9c09 100644 --- a/producer/SendResult.h +++ b/producer/SendResult.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_SEND_RESULT_H #define OMS_SEND_RESULT_H diff --git a/producer/TransactionStateCheckListener.h b/producer/TransactionStateCheckListener.h new file mode 100644 index 0000000..c791cbe --- /dev/null +++ b/producer/TransactionStateCheckListener.h @@ -0,0 +1,62 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OMS_TRANSACTION_CHECK_LISTENER_H +#define OMS_TRANSACTION_CHECK_LISTENER_H + +#include "Namespace.h" +#include "Message.h" +#include "producer/ExecutionContext.h" +#include "producer/CheckContext.h" +#include "Uncopyable.h" + +BEGIN_NAMESPACE_3(io, openmessaging, producer) + + /** + * Each executor will be associated with a transactional message, can be used to execute local transaction + * branch and submit the transaction status(commit or rollback). + *

+ * + * The associated message will be exposed to consumer when the local transaction has been committed, or be + * discarded if local transaction has been rolled back. + * + *

+ * If the executor don't submit the transaction status for a long time, the server may lookup it forwardly through + * {@link LocalTransactionBranchExecutor#checkLocalTransactionBranch(Message, CheckLocalTransactionBranchContext)} + * + * @version OMS 1.0 + * @since OMS 1.0 + */ + class TransactionStateCheckListener : private Uncopyable { + public: + virtual ~TransactionStateCheckListener() { + + } + /** + * Checks the status of the local transaction branch. + * + * @param message the associated message. + * @param checkContext the check context. + */ + virtual void check(const MessagePtr &message, const CheckContextPtr &checkContext) = 0; + + }; + + typedef NS::shared_ptr TransactionStateCheckListenerPtr; + +END_NAMESPACE_3(io, openmessaging, producer) + +#endif //OMS_TRANSACTION_CHECK_LISTENER_H diff --git a/producer/TransactionalSendResult.h b/producer/TransactionalSendResult.h new file mode 100644 index 0000000..2a90395 --- /dev/null +++ b/producer/TransactionalSendResult.h @@ -0,0 +1,63 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OMS_TRANSACTIONAL_SEND_RESULT_H +#define OMS_TRANSACTIONAL_SEND_RESULT_H + +#include + +#include "smart_pointer.h" +#include "Namespace.h" +#include "Uncopyable.h" + +BEGIN_NAMESPACE_3(io, openmessaging, producer) + + /** + * The result of sending a OMS message to server + * with the message id and some properties. + * + * @version OMS 1.0 + * @since OMS 1.0 + */ + class TransactionalSendResult : public SendResult { + public: + virtual ~TransactionalSendResult() { + + } + + /** + * The unique transactionId id related to the {@code TransactionResult} instance. + * + * @return the transactional id + */ + virtual std::string transactionId() = 0; + + /** + * Commits a transaction. + */ + virtual void commit() = 0; + + /** + * Rolls back a transaction. + */ + virtual void rollback() = 0; + }; + + typedef NS::shared_ptr TransactionalSendResultPtr; + +END_NAMESPACE_3(io, openmessaging, producer) + +#endif // OMS_TRANSACTIONAL_SEND_RESULT_H diff --git a/routing/Operator.h b/routing/Operator.h deleted file mode 100644 index fe0b8a9..0000000 --- a/routing/Operator.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef OMS_OPERATOR_H -#define OMS_OPERATOR_H - -#include "smart_pointer.h" -#include "KeyValue.h" -#include "Namespace.h" -#include "Uncopyable.h" - -BEGIN_NAMESPACE_3(io, openmessaging, routing) - - /** - * A {@code Operator} is used to handle the flowing messages in {@code Routing}. - * - * There are many kinds of {@code Operator}, expression operator, deduplicate operator, - * joiner operator, filter operator, rpc operator, and so on. - * - * @version OMS 1.0 - * @since OMS 1.0 - */ - class Operator : private Uncopyable { - public: - virtual ~Operator() { - - } - - virtual KeyValuePtr properties() = 0; - - virtual std::string expression() = 0; - }; - typedef NS::shared_ptr OperatorPtr; - -END_NAMESPACE_3(io, openmessaging, routing) - -#endif //OMS_OPERATOR_H diff --git a/routing/Routing.h b/routing/Routing.h deleted file mode 100644 index 726cb53..0000000 --- a/routing/Routing.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef OMS_ROUTING_H -#define OMS_ROUTING_H - -#include - -#include "ServiceLifecycle.h" -#include "Namespace.h" - -BEGIN_NAMESPACE_3(io, openmessaging, routing) - - class Routing : public virtual ServiceLifecycle { - public: - virtual ~Routing() { - - } - - virtual KeyValuePtr properties() = 0; - - virtual std::string source() = 0; - - virtual std::string destination() = 0; - - virtual std::string expression() = 0; - - virtual std::string routingName() = 0; - }; - typedef NS::shared_ptr RoutingPtr; - -END_NAMESPACE_3(io, openmessaging, routing) - -#endif //OMS_ROUTING_H diff --git a/samples/ProducerApp.cpp b/samples/ProducerApp.cpp new file mode 100644 index 0000000..47e9c3d --- /dev/null +++ b/samples/ProducerApp.cpp @@ -0,0 +1,73 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "OpenMessaging.h" +#include "producer/Producer.h" + +#include + +using namespace std; +using namespace io::openmessaging; + +int main(int argc, char *argv[]) { + + MessagingAccessPoint *messagingAccessPoint = + OMS.getMessagingAccessPoint("oms:rocketmq://alice@rocketmq.apache.org/us-east"); + + producer::ProducerPtr producer = messagingAccessPoint->createProducer(); + + interceptor::ProducerInterceptorPtr interceptor = new interceptor::ProducerInterceptor() { + @Override + public void preSend(MessagePtr &message, ContextPtr &attributes) { + } + + @Override + public void postSend(MessagePtr &message, ContextPtr &attributes) { + } + }; + producer->addInterceptor(interceptor); + + producer->start(); + + ByteMessagePtr message =producer->createMessage("NS://HELLO_QUEUE", new MessageBody("HELLO_BODY")); + + producer::SendResultPtr sendResult = producer.send(message); + cout<<"SendResult: " << sendResult << endl; + + //Sends a message to the specified destination async. + FuturePtr sendResultFuture = producer.sendAsync(message); + sendResult = sendResultFuture.get(1000); + cout<<"SendResult: " << sendResult << endl; + + //Sends a message to the specified destination in one way mode. + producer.sendOneway(message); + + //Sends messages to the specified destination in batch mode. + list messages(10); + for (int i = 0; i < 10; i++) { + MessagePtr msg = producer.createMessage("NS://HELLO_QUEUE", new MessageBody("HELLO_BODY")); + messages.push_back(msg); + } + producer.send(messages); + + producer.removeInterceptor(interceptor); + + producer.stop(); + + messages.clear(); + + return 0; +} diff --git a/samples/PullConsumerApp.cpp b/samples/PullConsumerApp.cpp new file mode 100644 index 0000000..ece25ff --- /dev/null +++ b/samples/PullConsumerApp.cpp @@ -0,0 +1,54 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "OpenMessaging.h" +#include "consumer/Consumer.h" + +#include + +using namespace std; +using namespace io::openmessaging; + +int main(int argc, char *argv[]) { + + MessagingAccessPoint *messagingAccessPoint = + OMS.getMessagingAccessPoint("oms:rocketmq://alice@rocketmq.apache.org/us-east"); + + consumer::ConsumerPtr consumer = messagingAccessPoint->createConsumer(); + + interceptor::ConsumerInterceptorPtr interceptor = new interceptor::ConsumerInterceptor() { + @Override + public void preReceive(MessagePtr &message, ContextPtr &attributes) { + } + + @Override + public void postReceive(MessagePtr &message, ContextPtr &attributes) { + } + }; + consumer->addInterceptor(interceptor); + + consumer->bindQueue("NS://HELLO_QUEUE"); + + consumer->start(); + + ByteMessagePtr message = consumer->receive(1000); + + cout<<"Receive Message: " << ByteMessagePtr << endl; + + consumer.ack(ByteMessagePtr->headers()->getMessageId()); + + return 0; +} diff --git a/shared_ptr.hpp b/shared_ptr.hpp index af3b561..84103ee 100644 --- a/shared_ptr.hpp +++ b/shared_ptr.hpp @@ -1,12 +1,20 @@ -/** - * @file shared_ptr.hpp - * @brief shared_ptr is a minimal implementation of smart pointer, a subset of the C++11 std::shared_ptr or boost::shared_ptr. +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Copyright (c) 2013-2014 Sebastien Rombauts (sebastien.rombauts@gmail.com) + * http://www.apache.org/licenses/LICENSE-2.0 * - * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt - * or copy at http://opensource.org/licenses/MIT) + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ + + #pragma once #include // NULL diff --git a/smart_pointer.h b/smart_pointer.h index afb77e8..558134a 100644 --- a/smart_pointer.h +++ b/smart_pointer.h @@ -1,3 +1,19 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef OMS_SMART_POINTER_H #define OMS_SMART_POINTER_H @@ -70,7 +86,7 @@ BEGIN_NAMESPACE_2(io, openmessaging) bool copy_; }; -typedef ManagedArray MessageBody; +typedef ManagedArray MessageBody; END_NAMESPACE_2(io, openmessaging)