2727from celery .contrib .methods import task
2828import redis
2929import logging
30+ from contracts import contract , new_contract
3031
3132logger = logging .getLogger (__name__ )
3233logger .setLevel (logging .DEBUG )
3334
3435DEFAULT_MAX_LENGTH = 10
3536
37+ new_contract ("method" , lambda x : x == "http-get" or x == "http-post" )
38+
39+ new_contract ("function" , lambda x : hasattr (x , "__call__" ))
40+
41+ new_contract ("redis" , lambda x : isinstance (x , (redis .Redis , redis .StrictRedis )))
42+
43+
3644try :
3745 # Check whether a custom Celery configuration module named "snowplow_celery_config" exists
3846 import snowplow_celery_config
@@ -50,8 +58,25 @@ class Consumer(object):
5058 Supports both GET and POST requests
5159 """
5260
61+ @contract
5362 def __init__ (self , endpoint , method = "http-get" , buffer_size = None , on_success = None , on_failure = None ):
54-
63+ """
64+ :param endpoint: The collector URL. Don't include "http://" - this is done automatically.
65+ :type endpoint: string
66+ :param method: The HTTP request method
67+ :type method: method
68+ :param buffer_size: The maximum number of queued events before the buffer is flushed. Default is 10.
69+ :type buffer_size: string | None
70+ :param on_success: Callback executed after every request in a flush is successful.
71+ Gets passed the number of events flushed.
72+ :type on_success: function | None
73+ :param on_failure: Callback executed after not every event in a flush is successful.
74+ Gets passed two arguments:
75+ 1) The number of events which were successfully sent
76+ 2) If method is "http-post": The unsent data in string form;
77+ If method is "http-get": An array of dictionaries corresponding to the unsent events' payloads
78+ :type on_failure: function | None
79+ """
5580 self .endpoint = Consumer .as_collector_uri (endpoint )
5681
5782 self .method = method
@@ -68,13 +93,23 @@ def __init__(self, endpoint, method="http-get", buffer_size=None, on_success=Non
6893 self .on_failure = on_failure
6994
7095 @staticmethod
96+ @contract
7197 def as_collector_uri (endpoint ):
98+ """
99+ :param endpoint: The raw endpoint provided by the user
100+ :type endpoint: string
101+ :rtype: string
102+ """
72103 return "http://" + endpoint + "/i"
73104
105+ @contract
74106 def input (self , payload ):
75107 """
76108 Adds an event to the buffer.
77109 If the maximum size has been reached, flushes the buffer.
110+
111+ :param payload: The name-value pairs for the event
112+ :type payload: dict(str:*)
78113 """
79114 self .buffer .append (payload )
80115 if len (self .buffer ) >= self .buffer_size :
@@ -85,7 +120,6 @@ def flush(self):
85120 """
86121 Sends all events in the buffer to the collector.
87122 """
88-
89123 if self .method == "http-post" :
90124 data = json .dumps (self .buffer )
91125 buffer_length = len (self .buffer )
@@ -120,13 +154,23 @@ def flush(self):
120154 else :
121155 logger .warn (self .method + ' is not a recognised HTTP method. Use "http-get" or "http-post".' )
122156
157+ @contract
123158 def http_post (self , data ):
159+ """
160+ :param data: The array of JSONs to be sent
161+ :type data: string
162+ """
124163 logger .debug ("Sending POST request..." )
125164 r = requests .post (self .endpoint , data = data )
126165 logger .debug ("POST request finished with status code: " + str (r .status_code ))
127166 return r
128167
168+ @contract
129169 def http_get (self , payload ):
170+ """
171+ :param payload: The event properties
172+ :type payload: dict(str:*)
173+ """
130174 logger .debug ("Sending GET request..." )
131175 r = requests .get (self .endpoint , params = payload )
132176 logger .debug ("GET request finished with status code: " + str (r .status_code ))
@@ -164,13 +208,24 @@ class RedisConsumer(object):
164208 """
165209 Sends Snowplow events to a Redis database
166210 """
211+ @contract
167212 def __init__ (self , rdb = None , key = "snowplow" ):
213+ """
214+ :param rdb: Optional custom Redis database
215+ :type rdb: redis | None
216+ :param key: The Redis key for the list of events
217+ :type key: string
218+ """
168219 if rdb is None :
169220 rdb = redis .StrictRedis ()
170221 self .rdb = rdb
171222 self .key = key
172223
173224 def input (self , payload ):
225+ """
226+ :param payload: The event properties
227+ :type payload: dict(str:*)
228+ """
174229 logger .debug ("Pushing event to Redis queue..." )
175230 self .rdb .rpush (self .key , json .dumps (payload ))
176231 logger .debug ("Finished sending event to Redis." )
0 commit comments