|
1 | 1 | # -*- coding: utf-8 -*- |
2 | 2 | import argparse |
| 3 | +import json |
3 | 4 | import logging |
| 5 | +import multiprocessing |
4 | 6 | import os |
5 | 7 | import socket |
6 | 8 | import time |
7 | 9 | import traceback |
| 10 | +from datetime import datetime, timezone |
8 | 11 |
|
9 | | -from Monitor import Monitor, MonitorLogHandler |
10 | | -from rc_config import SOCKET_HOST, SOCKET_PORT |
11 | 12 | from sseclient import SSEClient as EventSource |
12 | | -from rc import process |
13 | 13 |
|
| 14 | +from Monitor import Monitor, MonitorLogHandler |
| 15 | +from rc import process |
| 16 | +from rc_config import SOCKET_HOST, SOCKET_PORT |
14 | 17 |
|
15 | 18 | parser = argparse.ArgumentParser() |
16 | 19 | parser.add_argument('--sleep', type=int, default=60) |
| 20 | +parser.add_argument('--timeout', type=int, default=900) |
17 | 21 | parser.add_argument('-d', '--debug', action='store_const', dest='loglevel', const=logging.DEBUG) |
18 | 22 | parser.add_argument('-v', '--verbose', action='store_const', dest='loglevel', const=logging.INFO) |
19 | 23 | parser.set_defaults(loglevel=logging.WARNING) |
|
29 | 33 |
|
30 | 34 | os.environ['TZ'] = 'UTC' |
31 | 35 |
|
32 | | -url = 'https://stream.wikimedia.org/v2/stream/recentchange' |
| 36 | +URL = 'https://stream.wikimedia.org/v2/stream/recentchange' |
33 | 37 |
|
34 | 38 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
35 | 39 | sock.connect((SOCKET_HOST, SOCKET_PORT)) |
|
39 | 43 | 'User-Agent': M.wp_user_agent, |
40 | 44 | } |
41 | 45 |
|
42 | | -errorWaitTime = 1 |
43 | | -while True: |
44 | | - try: |
45 | | - for event in EventSource(url, headers=headers): |
46 | | - if event.event == 'message': |
47 | | - if len(event.data) == 0: |
48 | | - continue |
49 | 46 |
|
50 | | - logging.debug(event.data) |
| 47 | +def main(lastOffset): |
| 48 | + fullUrl = URL |
| 49 | + if lastOffset.value > 0: |
| 50 | + fullUrl += '?since={}'.format(datetime.fromtimestamp(lastOffset.value, tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")) |
| 51 | + for event in EventSource(fullUrl, headers=headers): |
| 52 | + if event.event == 'message': |
| 53 | + if len(event.data) == 0: |
| 54 | + continue |
| 55 | + |
| 56 | + logging.debug(event.data) |
| 57 | + |
| 58 | + try: |
| 59 | + change = json.loads(event.data) |
| 60 | + except json.decoder.JSONDecodeError as e: |
| 61 | + msg = 'UnicodeDecodeError: {}. {}'.format(e, event.data) |
| 62 | + logging.error(msg) |
| 63 | + continue |
| 64 | + process(change) |
| 65 | + lastOffset.value = int(change['timestamp']) |
51 | 66 |
|
52 | | - noError = True |
53 | 67 |
|
54 | | - data = event.data.encode('utf-8') |
55 | | - process(data) |
| 68 | +lastOffset = multiprocessing.Value('i', 0) |
| 69 | +while True: |
| 70 | + try: |
| 71 | + print('Last-Event-ID', lastOffset.value) |
| 72 | + p = multiprocessing.Process(target=main, args=(lastOffset,)) |
| 73 | + p.start() |
| 74 | + p.join(timeout=args.timeout) |
| 75 | + |
| 76 | + if p.is_alive(): |
| 77 | + p.terminate() |
| 78 | + p.join() |
56 | 79 |
|
57 | 80 | except Exception as e: |
58 | 81 | traceback.print_exc() |
59 | 82 | M.error(traceback.format_exc(), noRaise=True) |
60 | 83 |
|
61 | | - time.sleep(args.sleep) |
| 84 | + time.sleep(args.sleep) |
0 commit comments