Bulk subscribe support (mainly just to mirror JS)
This commit is contained in:
@@ -43,6 +43,20 @@ static json_t *cosmo_find_subscription(cosmo *instance, json_t *subject) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cosmo_send_command_locked(cosmo *instance, json_t *command) {
|
||||||
|
json_array_append_new(instance->command_queue, command);
|
||||||
|
instance->next_delay_ms = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes ownership of command.
|
||||||
|
static void cosmo_send_command(cosmo *instance, json_t *command) {
|
||||||
|
assert(command);
|
||||||
|
assert(!pthread_mutex_lock(&instance->lock));
|
||||||
|
cosmo_send_command_locked(instance, command);
|
||||||
|
assert(!pthread_cond_signal(&instance->cond));
|
||||||
|
assert(!pthread_mutex_unlock(&instance->lock));
|
||||||
|
}
|
||||||
|
|
||||||
static size_t cosmo_read_callback(void *ptr, size_t size, size_t nmemb, void *userp) {
|
static size_t cosmo_read_callback(void *ptr, size_t size, size_t nmemb, void *userp) {
|
||||||
cosmo_transfer *transfer = userp;
|
cosmo_transfer *transfer = userp;
|
||||||
size_t to_write = min(transfer->send_buf_len, size * nmemb);
|
size_t to_write = min(transfer->send_buf_len, size * nmemb);
|
||||||
@@ -326,8 +340,7 @@ static json_t *cosmo_send_rpc(cosmo *instance, json_t *commands, json_t *ack) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
json_array_append_new(instance->command_queue, cosmo_command("subscribe", arguments));
|
cosmo_send_command_locked(instance, cosmo_command("subscribe", arguments));
|
||||||
instance->next_delay_ms = 0;
|
|
||||||
}
|
}
|
||||||
assert(!pthread_mutex_unlock(&instance->lock));
|
assert(!pthread_mutex_unlock(&instance->lock));
|
||||||
}
|
}
|
||||||
@@ -410,16 +423,6 @@ static void *cosmo_thread_main(void *arg) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes ownership of command.
|
|
||||||
static void cosmo_send_command(cosmo *instance, json_t *command) {
|
|
||||||
assert(command);
|
|
||||||
assert(!pthread_mutex_lock(&instance->lock));
|
|
||||||
json_array_append_new(instance->command_queue, command);
|
|
||||||
instance->next_delay_ms = 0;
|
|
||||||
assert(!pthread_cond_signal(&instance->cond));
|
|
||||||
assert(!pthread_mutex_unlock(&instance->lock));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Public interface below
|
// Public interface below
|
||||||
|
|
||||||
@@ -444,26 +447,40 @@ json_t *cosmo_subject(const char *name, const char *readable_only_by, const char
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cosmo_subscribe(cosmo *instance, json_t *subject, const json_int_t messages, const json_int_t last_id) {
|
void cosmo_subscribe(cosmo *instance, json_t *subjects, const json_int_t messages, const json_int_t last_id) {
|
||||||
assert(!pthread_mutex_lock(&instance->lock));
|
if (json_is_array(subjects)) {
|
||||||
json_t *subscription = cosmo_find_subscription(instance, subject);
|
json_incref(subjects);
|
||||||
if (!subscription) {
|
} else {
|
||||||
subscription = json_pack("{sOs[]si}", "subject", subject, "messages", "state", SUBSCRIPTION_PENDING);
|
subjects = json_pack("[O]", subjects);
|
||||||
json_array_append_new(instance->subscriptions, subscription);
|
assert(subjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
json_t *arguments = json_pack("{sO}", "subject", subject);
|
assert(!pthread_mutex_lock(&instance->lock));
|
||||||
if (messages) {
|
size_t i;
|
||||||
json_object_set_new(arguments, "messages", json_integer(messages));
|
json_t *subject;
|
||||||
json_object_set_new(subscription, "num_messages", json_integer(messages));
|
json_array_foreach(subjects, i, subject) {
|
||||||
}
|
json_t *subscription = cosmo_find_subscription(instance, subject);
|
||||||
if (last_id) {
|
if (!subscription) {
|
||||||
json_object_set_new(arguments, "last_id", json_integer(last_id));
|
subscription = json_pack("{sOs[]si}", "subject", subject, "messages", "state", SUBSCRIPTION_PENDING);
|
||||||
json_object_set_new(subscription, "last_id", json_integer(last_id));
|
json_array_append_new(instance->subscriptions, subscription);
|
||||||
|
}
|
||||||
|
|
||||||
|
json_t *arguments = json_pack("{sO}", "subject", subject);
|
||||||
|
if (messages) {
|
||||||
|
json_object_set_new(arguments, "messages", json_integer(messages));
|
||||||
|
json_object_set_new(subscription, "num_messages", json_integer(messages));
|
||||||
|
}
|
||||||
|
if (last_id) {
|
||||||
|
json_object_set_new(arguments, "last_id", json_integer(last_id));
|
||||||
|
json_object_set_new(subscription, "last_id", json_integer(last_id));
|
||||||
|
}
|
||||||
|
cosmo_send_command_locked(instance, cosmo_command("subscribe", arguments));
|
||||||
}
|
}
|
||||||
assert(!pthread_mutex_unlock(&instance->lock));
|
assert(!pthread_mutex_unlock(&instance->lock));
|
||||||
|
|
||||||
cosmo_send_command(instance, cosmo_command("subscribe", arguments));
|
pthread_cond_signal(&instance->cond);
|
||||||
|
|
||||||
|
json_decref(subjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cosmo_unsubscribe(cosmo *instance, json_t *subject) {
|
void cosmo_unsubscribe(cosmo *instance, json_t *subject) {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ void cosmo_shutdown(cosmo *instance);
|
|||||||
const char *cosmo_current_profile(cosmo *instance);
|
const char *cosmo_current_profile(cosmo *instance);
|
||||||
|
|
||||||
json_t *cosmo_subject(const char *name, const char *readable_only_by, const char *writeable_only_by);
|
json_t *cosmo_subject(const char *name, const char *readable_only_by, const char *writeable_only_by);
|
||||||
void cosmo_subscribe(cosmo *instance, json_t *subject, const json_int_t messages, const json_int_t last_id);
|
void cosmo_subscribe(cosmo *instance, json_t *subjects, const json_int_t messages, const json_int_t last_id);
|
||||||
void cosmo_unsubscribe(cosmo *instance, json_t *subject);
|
void cosmo_unsubscribe(cosmo *instance, json_t *subject);
|
||||||
void cosmo_send_message(cosmo *instance, json_t *subject, json_t *message);
|
void cosmo_send_message(cosmo *instance, json_t *subject, json_t *message);
|
||||||
|
|
||||||
|
|||||||
@@ -226,12 +226,39 @@ bool test_resubscribe(test_state *state) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool test_bulk_subscribe(test_state *state) {
|
||||||
|
cosmo *client = create_client(state);
|
||||||
|
|
||||||
|
json_t *subject1 = random_subject(NULL, NULL);
|
||||||
|
json_t *subject2 = random_subject(NULL, NULL);
|
||||||
|
json_t *subjects = json_pack("[oo]", subject1, subject2);
|
||||||
|
cosmo_subscribe(client, subjects, -1, 0);
|
||||||
|
|
||||||
|
json_t *message_out = random_message();
|
||||||
|
cosmo_send_message(client, subject1, message_out);
|
||||||
|
const json_t *message_in = wait_for_message(state);
|
||||||
|
assert(json_equal(message_out, json_object_get(message_in, "message")));
|
||||||
|
json_decref(message_out);
|
||||||
|
|
||||||
|
message_out = random_message();
|
||||||
|
cosmo_send_message(client, subject2, message_out);
|
||||||
|
message_in = wait_for_message(state);
|
||||||
|
assert(json_equal(message_out, json_object_get(message_in, "message")));
|
||||||
|
json_decref(message_out);
|
||||||
|
|
||||||
|
json_decref(subjects);
|
||||||
|
|
||||||
|
cosmo_shutdown(client);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
RUN_TEST(test_create_shutdown);
|
RUN_TEST(test_create_shutdown);
|
||||||
RUN_TEST(test_connect_logout_fires);
|
RUN_TEST(test_connect_logout_fires);
|
||||||
RUN_TEST(test_message_round_trip);
|
RUN_TEST(test_message_round_trip);
|
||||||
RUN_TEST(test_resubscribe);
|
RUN_TEST(test_resubscribe);
|
||||||
RUN_TEST(test_reconnect);
|
RUN_TEST(test_reconnect);
|
||||||
|
RUN_TEST(test_bulk_subscribe);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user