|
18 | 18 | STOP_ASYNC_PRODUCER = -1
|
19 | 19 |
|
20 | 20 |
|
| 21 | +def _send_upstream(topic, queue, client, batch_time, batch_size, |
| 22 | + req_acks, ack_timeout): |
| 23 | + """ |
| 24 | + Listen on the queue for a specified number of messages or till |
| 25 | + a specified timeout and send them upstream to the brokers in one |
| 26 | + request |
| 27 | +
|
| 28 | + NOTE: Ideally, this should have been a method inside the Producer |
| 29 | + class. However, multiprocessing module has issues in windows. The |
| 30 | + functionality breaks unless this function is kept outside of a class |
| 31 | + """ |
| 32 | + stop = False |
| 33 | + client.reinit() |
| 34 | + |
| 35 | + while not stop: |
| 36 | + timeout = batch_time |
| 37 | + count = batch_size |
| 38 | + send_at = datetime.now() + timedelta(seconds=timeout) |
| 39 | + msgset = defaultdict(list) |
| 40 | + |
| 41 | + # Keep fetching till we gather enough messages or a |
| 42 | + # timeout is reached |
| 43 | + while count > 0 and timeout >= 0: |
| 44 | + try: |
| 45 | + partition, msg = queue.get(timeout=timeout) |
| 46 | + except Empty: |
| 47 | + break |
| 48 | + |
| 49 | + # Check if the controller has requested us to stop |
| 50 | + if partition == STOP_ASYNC_PRODUCER: |
| 51 | + stop = True |
| 52 | + break |
| 53 | + |
| 54 | + # Adjust the timeout to match the remaining period |
| 55 | + count -= 1 |
| 56 | + timeout = (send_at - datetime.now()).total_seconds() |
| 57 | + msgset[partition].append(msg) |
| 58 | + |
| 59 | + # Send collected requests upstream |
| 60 | + reqs = [] |
| 61 | + for partition, messages in msgset.items(): |
| 62 | + req = ProduceRequest(topic, partition, messages) |
| 63 | + reqs.append(req) |
| 64 | + |
| 65 | + try: |
| 66 | + client.send_produce_request(reqs, |
| 67 | + acks=req_acks, |
| 68 | + timeout=ack_timeout) |
| 69 | + except Exception as exp: |
| 70 | + log.error("Error sending message", exc_info=sys.exc_info()) |
| 71 | + |
| 72 | + |
21 | 73 | class Producer(object):
|
22 | 74 | """
|
23 | 75 | Base class to be used by producers
|
@@ -61,60 +113,22 @@ def __init__(self, client, async=False,
|
61 | 113 | self.async = async
|
62 | 114 | self.req_acks = req_acks
|
63 | 115 | self.ack_timeout = ack_timeout
|
64 |
| - self.batch_send = batch_send |
65 |
| - self.batch_size = batch_send_every_n |
66 |
| - self.batch_time = batch_send_every_t |
67 | 116 |
|
68 | 117 | if self.async:
|
69 | 118 | self.queue = Queue() # Messages are sent through this queue
|
70 |
| - self.proc = Process(target=self._send_upstream, args=(self.queue,)) |
71 |
| - self.proc.daemon = True # Process will die if main thread exits |
| 119 | + self.proc = Process(target=_send_upstream, |
| 120 | + args=(self.topic, |
| 121 | + self.queue, |
| 122 | + self.client.copy(), |
| 123 | + batch_send_every_t, |
| 124 | + batch_send_every_n, |
| 125 | + self.req_acks, |
| 126 | + self.ack_timeout)) |
| 127 | + |
| 128 | + # Process will die if main thread exits |
| 129 | + self.proc.daemon = True |
72 | 130 | self.proc.start()
|
73 | 131 |
|
74 |
| - def _send_upstream(self, queue): |
75 |
| - """ |
76 |
| - Listen on the queue for a specified number of messages or till |
77 |
| - a specified timeout and send them upstream to the brokers in one |
78 |
| - request |
79 |
| - """ |
80 |
| - stop = False |
81 |
| - |
82 |
| - while not stop: |
83 |
| - timeout = self.batch_time |
84 |
| - send_at = datetime.now() + timedelta(seconds=timeout) |
85 |
| - count = self.batch_size |
86 |
| - msgset = defaultdict(list) |
87 |
| - |
88 |
| - # Keep fetching till we gather enough messages or a |
89 |
| - # timeout is reached |
90 |
| - while count > 0 and timeout >= 0: |
91 |
| - try: |
92 |
| - partition, msg = queue.get(timeout=timeout) |
93 |
| - except Empty: |
94 |
| - break |
95 |
| - |
96 |
| - # Check if the controller has requested us to stop |
97 |
| - if partition == STOP_ASYNC_PRODUCER: |
98 |
| - stop = True |
99 |
| - break |
100 |
| - |
101 |
| - # Adjust the timeout to match the remaining period |
102 |
| - count -= 1 |
103 |
| - timeout = (send_at - datetime.now()).total_seconds() |
104 |
| - msgset[partition].append(msg) |
105 |
| - |
106 |
| - # Send collected requests upstream |
107 |
| - reqs = [] |
108 |
| - for partition, messages in msgset.items(): |
109 |
| - req = ProduceRequest(self.topic, partition, messages) |
110 |
| - reqs.append(req) |
111 |
| - |
112 |
| - try: |
113 |
| - self.client.send_produce_request(reqs, acks=self.req_acks, |
114 |
| - timeout=self.ack_timeout) |
115 |
| - except Exception: |
116 |
| - log.error("Error sending message", exc_info=sys.exc_info()) |
117 |
| - |
118 | 132 | def send_messages(self, partition, *msg):
|
119 | 133 | """
|
120 | 134 | Helper method to send produce requests
|
|
0 commit comments