You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

213 lines
5.3 KiB

  1. /*
  2. * node-rdkafka - Node.js wrapper for RdKafka C/C++ library
  3. *
  4. * Copyright (c) 2016 Blizzard Entertainment
  5. *
  6. * This software may be modified and distributed under the terms
  7. * of the MIT license. See the LICENSE.txt file for details.
  8. */
  9. 'use strict';
  10. module.exports = {
  11. create: createAdminClient,
  12. };
  13. var Client = require('./client');
  14. var util = require('util');
  15. var Kafka = require('../librdkafka');
  16. var LibrdKafkaError = require('./error');
  17. var shallowCopy = require('./util').shallowCopy;
  18. /**
  19. * Create a new AdminClient for making topics, partitions, and more.
  20. *
  21. * This is a factory method because it immediately starts an
  22. * active handle with the brokers.
  23. *
  24. */
  25. function createAdminClient(conf) {
  26. var client = new AdminClient(conf);
  27. // Wrap the error so we throw if it failed with some context
  28. LibrdKafkaError.wrap(client.connect(), true);
  29. // Return the client if we succeeded
  30. return client;
  31. }
  32. /**
  33. * AdminClient class for administering Kafka
  34. *
  35. * This client is the way you can interface with the Kafka Admin APIs.
  36. * This class should not be made using the constructor, but instead
  37. * should be made using the factory method.
  38. *
  39. * <code>
  40. * var client = AdminClient.create({ ... });
  41. * </code>
  42. *
  43. * Once you instantiate this object, it will have a handle to the kafka broker.
  44. * Unlike the other node-rdkafka classes, this class does not ensure that
  45. * it is connected to the upstream broker. Instead, making an action will
  46. * validate that.
  47. *
  48. * @param {object} conf - Key value pairs to configure the admin client
  49. * topic configuration
  50. * @constructor
  51. */
  52. function AdminClient(conf) {
  53. if (!(this instanceof AdminClient)) {
  54. return new AdminClient(conf);
  55. }
  56. conf = shallowCopy(conf);
  57. /**
  58. * NewTopic model.
  59. *
  60. * This is the representation of a new message that is requested to be made
  61. * using the Admin client.
  62. *
  63. * @typedef {object} AdminClient~NewTopic
  64. * @property {string} topic - the topic name to create
  65. * @property {number} num_partitions - the number of partitions to give the topic
  66. * @property {number} replication_factor - the replication factor of the topic
  67. * @property {object} config - a list of key values to be passed as configuration
  68. * for the topic.
  69. */
  70. this._client = new Kafka.AdminClient(conf);
  71. this._isConnected = false;
  72. this.globalConfig = conf;
  73. }
  74. /**
  75. * Connect using the admin client.
  76. *
  77. * Should be run using the factory method, so should never
  78. * need to be called outside.
  79. *
  80. * Unlike the other connect methods, this one is synchronous.
  81. */
  82. AdminClient.prototype.connect = function() {
  83. LibrdKafkaError.wrap(this._client.connect(), true);
  84. this._isConnected = true;
  85. };
  86. /**
  87. * Disconnect the admin client.
  88. *
  89. * This is a synchronous method, but all it does is clean up
  90. * some memory and shut some threads down
  91. */
  92. AdminClient.prototype.disconnect = function() {
  93. LibrdKafkaError.wrap(this._client.disconnect(), true);
  94. this._isConnected = false;
  95. };
  96. /**
  97. * Create a topic with a given config.
  98. *
  99. * @param {NewTopic} topic - Topic to create.
  100. * @param {number} timeout - Number of milliseconds to wait while trying to create the topic.
  101. * @param {function} cb - The callback to be executed when finished
  102. */
  103. AdminClient.prototype.createTopic = function(topic, timeout, cb) {
  104. if (!this._isConnected) {
  105. throw new Error('Client is disconnected');
  106. }
  107. if (typeof timeout === 'function') {
  108. cb = timeout;
  109. timeout = 5000;
  110. }
  111. if (!timeout) {
  112. timeout = 5000;
  113. }
  114. this._client.createTopic(topic, timeout, function(err) {
  115. if (err) {
  116. if (cb) {
  117. cb(LibrdKafkaError.create(err));
  118. }
  119. return;
  120. }
  121. if (cb) {
  122. cb();
  123. }
  124. });
  125. };
  126. /**
  127. * Delete a topic.
  128. *
  129. * @param {string} topic - The topic to delete, by name.
  130. * @param {number} timeout - Number of milliseconds to wait while trying to delete the topic.
  131. * @param {function} cb - The callback to be executed when finished
  132. */
  133. AdminClient.prototype.deleteTopic = function(topic, timeout, cb) {
  134. if (!this._isConnected) {
  135. throw new Error('Client is disconnected');
  136. }
  137. if (typeof timeout === 'function') {
  138. cb = timeout;
  139. timeout = 5000;
  140. }
  141. if (!timeout) {
  142. timeout = 5000;
  143. }
  144. this._client.deleteTopic(topic, timeout, function(err) {
  145. if (err) {
  146. if (cb) {
  147. cb(LibrdKafkaError.create(err));
  148. }
  149. return;
  150. }
  151. if (cb) {
  152. cb();
  153. }
  154. });
  155. };
  156. /**
  157. * Create new partitions for a topic.
  158. *
  159. * @param {string} topic - The topic to add partitions to, by name.
  160. * @param {number} totalPartitions - The total number of partitions the topic should have
  161. * after the request
  162. * @param {number} timeout - Number of milliseconds to wait while trying to create the partitions.
  163. * @param {function} cb - The callback to be executed when finished
  164. */
  165. AdminClient.prototype.createPartitions = function(topic, totalPartitions, timeout, cb) {
  166. if (!this._isConnected) {
  167. throw new Error('Client is disconnected');
  168. }
  169. if (typeof timeout === 'function') {
  170. cb = timeout;
  171. timeout = 5000;
  172. }
  173. if (!timeout) {
  174. timeout = 5000;
  175. }
  176. this._client.createPartitions(topic, totalPartitions, timeout, function(err) {
  177. if (err) {
  178. if (cb) {
  179. cb(LibrdKafkaError.create(err));
  180. }
  181. return;
  182. }
  183. if (cb) {
  184. cb();
  185. }
  186. });
  187. };