dnaStreaming 2.0.2__tar.gz → 2.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. dnastreaming-2.1.0/LICENSE +21 -0
  2. dnastreaming-2.1.0/PKG-INFO +255 -0
  3. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/README.rst +30 -37
  4. dnastreaming-2.1.0/dnaStreaming/config.py +109 -0
  5. dnastreaming-2.1.0/dnaStreaming/customer_config.json +5 -0
  6. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/dnaStreaming/demo/show_stream.py +6 -1
  7. dnastreaming-2.1.0/dnaStreaming/listener.py +114 -0
  8. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/dnaStreaming/services/credentials_service.py +1 -1
  9. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/dnaStreaming/test/test_config.py +0 -50
  10. dnastreaming-2.1.0/dnaStreaming.egg-info/PKG-INFO +255 -0
  11. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/dnaStreaming.egg-info/SOURCES.txt +1 -0
  12. dnastreaming-2.1.0/dnaStreaming.egg-info/requires.txt +8 -0
  13. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/setup.py +11 -8
  14. dnaStreaming-2.0.2/PKG-INFO +0 -254
  15. dnaStreaming-2.0.2/dnaStreaming/config.py +0 -202
  16. dnaStreaming-2.0.2/dnaStreaming/customer_config.json +0 -8
  17. dnaStreaming-2.0.2/dnaStreaming/listener.py +0 -125
  18. dnaStreaming-2.0.2/dnaStreaming.egg-info/PKG-INFO +0 -254
  19. dnaStreaming-2.0.2/dnaStreaming.egg-info/requires.txt +0 -8
  20. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/MANIFEST.in +0 -0
  21. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/dnaStreaming/__init__.py +0 -0
  22. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/dnaStreaming/demo/__init__.py +0 -0
  23. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/dnaStreaming/demo/pubsub_stream.py +0 -0
  24. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/dnaStreaming/demo/show_stream_async.py +0 -0
  25. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/dnaStreaming/services/__init__.py +0 -0
  26. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/dnaStreaming/services/authentication_service.py +0 -0
  27. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/dnaStreaming/services/pubsub_service.py +0 -0
  28. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/dnaStreaming/test/__init__.py +0 -0
  29. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/dnaStreaming.egg-info/dependency_links.txt +0 -0
  30. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/dnaStreaming.egg-info/top_level.txt +0 -0
  31. {dnaStreaming-2.0.2 → dnastreaming-2.1.0}/setup.cfg +0 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016 Dow Jones Corporation
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,255 @@
1
+ Metadata-Version: 2.1
2
+ Name: dnaStreaming
3
+ Version: 2.1.0
4
+ Summary: Dow Jones DNA Streaming Project
5
+ Home-page: https://github.com/dowjones/dj-dna-streams-python
6
+ Download-URL: https://github.com/dowjones/dj-dna-streams-python/archive/release-2.1.0.tar.gz
7
+ Author: Zachary Kagan
8
+ Author-email: zachary.kagan@dowjones.com
9
+ License: MIT
10
+ Keywords: DOWJONES,FACTIVA,STREAMS
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Description-Content-Type: text/x-rst
16
+ License-File: LICENSE
17
+ Requires-Dist: googleapis-common-protos>=1.56.4
18
+ Requires-Dist: google-auth>=2.11.0
19
+ Requires-Dist: google-cloud-pubsub==2.13.6
20
+ Requires-Dist: google-cloud-core==2.3.2
21
+ Requires-Dist: google-api-core==2.10.1
22
+ Requires-Dist: mock>=3.0.5
23
+ Requires-Dist: oauth2client>=4.1.3
24
+ Requires-Dist: requests>=2.28.0
25
+
26
+ How To Use
27
+ ----------
28
+
29
+ This a Python3 library is for Dow Jones customers consuming data from a Dow Jones Factiva Stream.
30
+
31
+ To use this we recommend 'pip installing' this by making the following addition to your requirements.txt:
32
+
33
+ .. code-block::
34
+
35
+ # To fetch latest version from PyPi
36
+ dnaStreaming
37
+
38
+ # to fetch latest version from GitHub
39
+ git+https://github.com/dowjones/dj-dna-streams-python#egg=dnaStreaming
40
+
41
+
42
+ Auth
43
+ -----------
44
+
45
+ There is currently one way to authenticate, which is by using **your user key**.
46
+
47
+ Configuring
48
+ ___________
49
+
50
+ To run this code, you need to provide credentials from one of the authentication methods and your subscriptions. There are 3 ways to do this: you can set environment variables, use a configuration file or pass an argument to a constructor.
51
+
52
+ 1. Set environment variables.
53
+ ###################################################################
54
+
55
+ To set your service account credentials, set the `USER_KEY` environment variable:
56
+
57
+ .. code-block::
58
+
59
+ export USER_KEY="1234567890-098765432"
60
+
61
+
62
+ To set your subscription ID, simply set an environment variable named 'SUBSCRIPTION_ID' like so
63
+
64
+ .. code-block::
65
+
66
+ export SUBSCRIPTION_ID="ABC1234567889"
67
+
68
+
69
+ The code above is the command line expression for setting this environment variable on Mac OSX. Other operating systems might have a slightly different techniques for setting environment variables on the command line.
70
+
71
+ 2. Using the configuration file.
72
+ ###################################################################
73
+
74
+ In this codebase you will find a file named 'customer_config.json'. You are not required to use this file. If you prefer to use this option, fill the JSON object within by adding your user key and your subscription ID. Remember that this is a JSON file so follow basic JSON formatting and syntax conventions.
75
+
76
+ > The listener will search for the `customer_config.json` file inside your `$HOME` directory by default.
77
+
78
+ If you prefer using an explicit path to your configuration file, pass the absolute path to the Listener constructor like so:
79
+
80
+ .. code-block:: python
81
+
82
+ from dnaStreaming.listener import Listener
83
+ # Config. file authentication
84
+ listener = Listener(config_file=<ABSOLUTE PATH TO YOUR CONFIG. FILE>)
85
+
86
+
87
+ 3. Pass in variables as function arguments.
88
+ ###################################################################
89
+
90
+ You may pass your user key to the Listener constructor and your subscription ID to the listen method like so:
91
+
92
+ .. code-block:: python
93
+
94
+ from dnaStreaming.listener import Listener
95
+ # Use the user_key argument to provide your credentials
96
+ listener = Listener(user_key=<YOUR USER KEY>)
97
+ # Use the subscription_id argument to provide your subscription id to the listener
98
+ listener.listen(callback, subscription_id=<YOUR SUBSCRIPTION ID>)
99
+ # same parameter for the async variation
100
+ listener.listen_async(callback, subscription_id=<YOUR SUBSCRIPTION ID>)
101
+
102
+
103
+ Or you may use the environment variables.
104
+ Remember that passing credentials and subscription ID(s) in this way will override the environment variable and the config file settings.
105
+
106
+ .. code-block:: python
107
+
108
+ from dnaStreaming.listener import Listener
109
+
110
+ listener = Listener()
111
+
112
+
113
+ 4. Listening to messages
114
+ ###################################################################
115
+
116
+ You may want to listen messages synchronously like so:
117
+
118
+ .. code-block:: python
119
+
120
+ def callback(message, subscription_id):
121
+ print('Subscription ID: {}: Message: {}'.format(subscription_id, message.data.__str__()))
122
+ return True # If desired return False to stop the message flow. This will unblock the process as well.
123
+
124
+ listener.listen(callback, maximum_messages=10) # Omitting maximum_messages means you will continue to get messages as they appear. Can be a firehose. Use with caution.
125
+ # You may pass subscription ID as a parameter to the listen function
126
+
127
+
128
+ You may want to listen messages asynchronously like so:
129
+
130
+ .. code-block:: python
131
+
132
+ def callback(message, subscription_id):
133
+ print('Subscription ID: {}: Message: {}'.format(subscription_id, message.data.__str__()))
134
+
135
+ future = listener.listen_async(callback)
136
+ # After calling `listed_async` you need to keep the main thread alive.
137
+
138
+ for count in range(0, 5):
139
+ sleep(1)
140
+
141
+ # Stop receiving messages after 5 seconds
142
+ if future.running():
143
+ future.cancel()
144
+
145
+
146
+ Log Files
147
+ _________
148
+
149
+ Very minimal logging is written to the module's path 'logs/dj-dna-streaming-python.log'. To keep maintenance simple this log is overwritten every time the app starts.
150
+
151
+
152
+ Testing
153
+ _______
154
+
155
+ .. code-block::
156
+
157
+ cd dnaStreaming/test
158
+ pip install -r requirements.txt
159
+ py.test . -s
160
+
161
+
162
+ or, alternatively, to test against python2.7 and python3.5:
163
+
164
+ .. code-block::
165
+
166
+ tox
167
+
168
+
169
+ Flake8
170
+ ______
171
+
172
+ If you are maintaining this library, ensure you run flake8 before you commit. At project root command line:
173
+
174
+ .. code-block::
175
+
176
+ flake8 ./dnaStreaming ./tests
177
+
178
+
179
+ Running the Demonstration Code/Development
180
+ __________________________________________
181
+
182
+ If you are enhancing this codebase (and not just using it as a library), follow these example MacOS steps:
183
+
184
+ 1. Checkout the Project from Git.
185
+ ###################################################################
186
+
187
+ 2. Go to the Project Root.
188
+ ###################################################################
189
+
190
+ 3. Create a Virtual Environment.
191
+ ###################################################################
192
+
193
+ .. code-block::
194
+
195
+ virtualenv venv
196
+
197
+
198
+ 4. Then activate the virutal environment by executing this command:
199
+ ###################################################################
200
+
201
+ .. code-block::
202
+
203
+ source ./venv/bin/activate
204
+
205
+
206
+ 5. Install the Dependencies
207
+ ###################################################################
208
+
209
+ .. code-block::
210
+
211
+ pip install -r requirements.txt
212
+
213
+
214
+ 6. Install the App:
215
+ ###################################################################
216
+
217
+ .. code-block::
218
+
219
+ python setup.py install
220
+
221
+
222
+ 7. Set the Configuration Variables
223
+ ###################################################################
224
+
225
+ See the config section.
226
+
227
+ 8. Run the Demo Code
228
+ ###################################################################
229
+
230
+ Running Non-Docker Demo:
231
+
232
+ Execute the following at the project root:
233
+
234
+ .. code-block::
235
+
236
+ python ./dnaStreaming/demo/show_stream.py -s
237
+
238
+
239
+ Or
240
+
241
+ .. code-block::
242
+
243
+ python ./dnaStreaming/demo/show_stream_async.py -s
244
+
245
+
246
+ Running Docker Demo
247
+
248
+ Execute the following at the project root:
249
+
250
+ .. code-block::
251
+
252
+ docker run -it \
253
+ -e USER_KEY=<your user KEY> \
254
+ -e SUBSCRIPTION_ID=<your subscription ID> \
255
+ dj-dna-streaming-python
@@ -7,31 +7,32 @@ To use this we recommend 'pip installing' this by making the following addition
7
7
 
8
8
  .. code-block::
9
9
 
10
- git+https://git@github.com/dowjones/dj-dna-streams-python#egg=dj-dna-streams-python
10
+ # To fetch latest version from PyPi
11
+ dnaStreaming
12
+
13
+ # to fetch latest version from GitHub
14
+ git+https://github.com/dowjones/dj-dna-streams-python#egg=dnaStreaming
11
15
 
12
16
 
13
17
  Auth
14
18
  -----------
15
19
 
16
- There are general two ways to authenticate.
17
-
18
- - Your User Key
19
-
20
- - UserId, ClientId, and Password
21
-
20
+ There is currently one way to authenticate, which is by using **your user key**.
22
21
 
23
22
  Configuring
24
23
  ___________
25
24
 
26
- To run this code, you need to provide credentials from one of the authentication methods and your subscriptions. There are 3 ways to do this. You can either set environment variables or you can use a configuration file.
25
+ To run this code, you need to provide credentials from one of the authentication methods and your subscriptions. There are 3 ways to do this: you can set environment variables, use a configuration file or pass an argument to a constructor.
27
26
 
28
27
  1. Set environment variables.
29
28
  ###################################################################
30
29
 
31
- To set your service account credentials, set either:
30
+ To set your service account credentials, set the `USER_KEY` environment variable:
31
+
32
+ .. code-block::
33
+
34
+ export USER_KEY="1234567890-098765432"
32
35
 
33
- - An environment variable named 'USER_KEY'.
34
- - Three environment variable named 'USER_ID', 'CLIENT_ID', and 'PASSWORD'.
35
36
 
36
37
  To set your subscription ID, simply set an environment variable named 'SUBSCRIPTION_ID' like so
37
38
 
@@ -45,21 +46,33 @@ The code above is the command line expression for setting this environment varia
45
46
  2. Using the configuration file.
46
47
  ###################################################################
47
48
 
48
- In this codebase you will find a file named 'customer_config.json'. You are not required to use this file. If you prefer to use this configuration file, follow these directions: Open this file and add your service account credentials. Then add your subscription IDs. Remember that this is a JSON file so follow basic JSON formatting and syntax conventions.
49
+ In this codebase you will find a file named 'customer_config.json'. You are not required to use this file. If you prefer to use this option, fill the JSON object within by adding your user key and your subscription ID. Remember that this is a JSON file so follow basic JSON formatting and syntax conventions.
50
+
51
+ > The listener will search for the `customer_config.json` file inside your `$HOME` directory by default.
52
+
53
+ If you prefer using an explicit path to your configuration file, pass the absolute path to the Listener constructor like so:
54
+
55
+ .. code-block:: python
56
+
57
+ from dnaStreaming.listener import Listener
58
+ # Config. file authentication
59
+ listener = Listener(config_file=<ABSOLUTE PATH TO YOUR CONFIG. FILE>)
60
+
49
61
 
50
62
  3. Pass in variables as function arguments.
51
63
  ###################################################################
52
64
 
53
- You may pass your service account credentials (user_id, client_id, and password) to the Listener constructor like so:
65
+ You may pass your user key to the Listener constructor and your subscription ID to the listen method like so:
54
66
 
55
67
  .. code-block:: python
56
68
 
57
69
  from dnaStreaming.listener import Listener
58
- # User key authentication
70
+ # Use the user_key argument to provide your credentials
59
71
  listener = Listener(user_key=<YOUR USER KEY>)
60
-
61
- # UserId, ClientId and Password authentication
62
- listener = Listener(user_id=<YOUR USER ID>, client_id=<YOUR_CLIENT_ID>, password=<YOUR_PASSWORD>)
72
+ # Use the subscription_id argument to provide your subscription id to the listener
73
+ listener.listen(callback, subscription_id=<YOUR SUBSCRIPTION ID>)
74
+ # same parameter for the async variation
75
+ listener.listen_async(callback, subscription_id=<YOUR SUBSCRIPTION ID>)
63
76
 
64
77
 
65
78
  Or you may use the environment variables.
@@ -205,30 +218,10 @@ Or
205
218
  python ./dnaStreaming/demo/show_stream_async.py -s
206
219
 
207
220
 
208
- If you are having `ImportError: No module named ...` run this in your terminal before running the demo:
209
-
210
- .. code-block::
211
-
212
- export PYTHONPATH='.'
213
-
214
-
215
221
  Running Docker Demo
216
222
 
217
223
  Execute the following at the project root:
218
224
 
219
- .. code-block::
220
-
221
- docker build -f ./DockerfileDemo -t dj-dna-streaming-python .
222
-
223
- docker run -it \
224
- -e USER_ID=<your user ID> \
225
- -e CLIENT_ID=<your client ID> \
226
- -e PASSWORD=<your password> \
227
- -e SUBSCRIPTION_ID=<your subscription ID> \
228
- dj-dna-streaming-python
229
-
230
- or:
231
-
232
225
  .. code-block::
233
226
 
234
227
  docker run -it \
@@ -0,0 +1,109 @@
1
+ from __future__ import absolute_import, division
2
+
3
+ import errno
4
+ import json
5
+ import os
6
+ from pathlib import Path
7
+
8
+ class Config(object):
9
+
10
+ DEFAULT_HOST = 'https://api.dowjones.com'
11
+
12
+ DEFAULT_CUST_CONFIG_PATH = str(Path.home()) + '/customer_config.json'
13
+ ENV_VAR_SUBSCRIPTION_ID = 'SUBSCRIPTION_ID'
14
+ ENV_VAR_USER_KEY = 'USER_KEY'
15
+ ENV_VAR_SERVICE_ACCOUNT_ID = 'SERVICE_ACCOUNT_ID'
16
+ ENV_VAR_API_HOST = 'API_HOST'
17
+
18
+ def __init__(self, service_account_id=None, user_key=None, config_file=None):
19
+ self.customer_config_path = self.DEFAULT_CUST_CONFIG_PATH if config_file is None else config_file
20
+ self.initialized = False
21
+ self.service_account_id = service_account_id
22
+ self.user_key = user_key
23
+
24
+ self.headers = None
25
+
26
+ def _initialize(self):
27
+ self._validate()
28
+
29
+ with open(self.customer_config_path, 'r') as f:
30
+ self.customer_config = json.load(f)
31
+
32
+ self.initialized = True
33
+ self.headers = None
34
+
35
+ def _validate(self):
36
+ if not os.path.isfile(self.customer_config_path):
37
+ raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), self.customer_config_path)
38
+
39
+ if not os.access(self.customer_config_path, os.R_OK):
40
+ raise Exception('Encountered permission problem reading file from path \'{}\'.'.format(self.customer_config_path))
41
+
42
+ def get_headers(self):
43
+ if self.headers:
44
+ return self.headers
45
+ else:
46
+ self.headers = self.get_authentication_headers()
47
+ return self.headers
48
+
49
+ def get_authentication_headers(self):
50
+
51
+ user_key = self.get_user_key()
52
+ if user_key:
53
+ return {
54
+ 'user-key': user_key
55
+ }
56
+
57
+ else:
58
+ msg = """
59
+ Unable to find credentials. Specify your account credentials by choosing one of the following ways:
60
+ - set your user key to an env var under the name 'USER_KEY'
61
+ - place your customer_config.json file in your home directory (e.g. ~/, $HOME/)
62
+ - pass the absolute path of your customer_config.json file to the constructor of the Listener class
63
+ - pass the user key as a parameter to the constructor of the Listener class
64
+ """
65
+ raise Exception(msg)
66
+
67
+ def get_uri_context(self):
68
+ host = os.getenv(self.ENV_VAR_API_HOST, self.DEFAULT_HOST)
69
+ return host
70
+
71
+ # in the following two methods, note that we use "SERVICE_ACCOUNT_ID" as a legacy,
72
+ # alternate name for the "USER_KEY" parameter, from the customer's perspective
73
+ def get_user_key(self):
74
+ user_key = self.user_key if self.user_key else self.service_account_id
75
+
76
+ if user_key is None:
77
+ user_key = os.getenv(self.ENV_VAR_USER_KEY,
78
+ os.getenv(self.ENV_VAR_SERVICE_ACCOUNT_ID))
79
+
80
+ if user_key is None:
81
+ user_key = self._user_key_id_from_file()
82
+
83
+ return user_key
84
+
85
+ def _user_key_id_from_file(self):
86
+ if not self.initialized:
87
+ self._initialize()
88
+
89
+ return self.customer_config.get('user_key',
90
+ self.customer_config.get('service_account_id'))
91
+
92
+ def subscription(self):
93
+ if os.getenv(self.ENV_VAR_SUBSCRIPTION_ID) is not None:
94
+ subscription = os.getenv(self.ENV_VAR_SUBSCRIPTION_ID)
95
+ else:
96
+ subscription = self._subscription_id_from_file()
97
+
98
+ return subscription
99
+
100
+ def _set_customer_config_path(self, path):
101
+ self.customer_config_path = path
102
+ self._initialize()
103
+
104
+ def _subscription_id_from_file(self):
105
+ if not self.initialized:
106
+ self._initialize()
107
+
108
+ return self.customer_config['subscription_id']
109
+
@@ -0,0 +1,5 @@
1
+ {
2
+
3
+ "user_key": "",
4
+ "subscription_id": ""
5
+ }
@@ -6,7 +6,12 @@ quiet_demo = os.getenv('QUIET_DEMO', "false") == "true"
6
6
  print("\n[ACTIVITY] Receiving messages (SYNC)...\n[0]", end='')
7
7
 
8
8
 
9
- def callback(message, subscription_id, file_handle=None):
9
+ def callback(message, subscription_id):
10
+ # Replace the code below with the custom operations you'd like to apply to each article (message)
11
+ # like writing to a file, database, or pushing the message to a separate message broker system.
12
+ # This demo only prints some message details.
13
+ # Subscription id parameter is provided and can be used for auditing purposes.
14
+
10
15
  callback.counter += 1
11
16
  if not quiet_demo:
12
17
  if message['action'] != 'del':
@@ -0,0 +1,114 @@
1
+ import time
2
+ import requests
3
+ import json
4
+ from threading import Thread
5
+
6
+ from google.api_core.exceptions import GoogleAPICallError, NotFound
7
+ from google import pubsub_v1
8
+
9
+ from dnaStreaming import logger
10
+ from dnaStreaming.config import Config
11
+ from dnaStreaming.services import pubsub_service, credentials_service
12
+
13
+
14
+ class Listener(object):
15
+ DEFAULT_UNLIMITED_MESSAGES = None
16
+
17
+ def __init__(self, service_account_id=None, user_key=None, config_file=None):
18
+ config = Config(service_account_id, user_key, config_file)
19
+ self._initialize(config)
20
+ self.current_subscription_index = 0
21
+
22
+ def _initialize(self, config):
23
+ self.config = config
24
+
25
+ def listen(self, on_message_callback, maximum_messages=DEFAULT_UNLIMITED_MESSAGES, subscription_id="", batch_size=10):
26
+ pubsub_client = pubsub_service.get_client(self.config)
27
+
28
+ subscription_id = subscription_id or self.config.subscription()
29
+ if not subscription_id:
30
+ raise Exception(
31
+ 'No subscription specified. You must specify the subscription ID either through an environment ' +
32
+ 'variable, a config file or by passing the value to the method.')
33
+
34
+ streaming_credentials = credentials_service.fetch_credentials(
35
+ self.config)
36
+ subscription_path = pubsub_client.subscription_path(
37
+ streaming_credentials['project_id'], subscription_id)
38
+
39
+ logger.info(
40
+ 'Listeners for subscriptions have been configured, set and await message arrival.')
41
+
42
+ count = 0
43
+ while maximum_messages is None or count < maximum_messages:
44
+ try:
45
+ if maximum_messages is not None:
46
+ batch_size = min(batch_size, maximum_messages - count)
47
+
48
+ pull_request = pubsub_v1.PullRequest(
49
+ subscription=subscription_path,
50
+ max_messages=batch_size,
51
+ )
52
+ results = pubsub_client.pull(request=pull_request)
53
+
54
+ if results:
55
+ if len(results.received_messages) > 0:
56
+ for message in results.received_messages:
57
+
58
+ pubsub_msg = json.loads(message.message.data)
59
+ logger.info("Received news message with ID: {}".format(
60
+ pubsub_msg['data'][0]['id']))
61
+ news_msg = pubsub_msg['data'][0]['attributes']
62
+
63
+ keep_message_flow = on_message_callback(
64
+ news_msg, subscription_id)
65
+
66
+ if not keep_message_flow:
67
+ logger.info(
68
+ 'Callback function returned False or falsy. Message flow stopped.')
69
+ return
70
+
71
+ ack_request = {
72
+ "subscription": subscription_path,
73
+ "ack_ids": [message.ack_id],
74
+ }
75
+ pubsub_client.acknowledge(request=ack_request)
76
+ count += 1
77
+
78
+ except GoogleAPICallError as e:
79
+ if isinstance(e, NotFound):
80
+ raise e
81
+ logger.error(
82
+ "Encountered a problem while trying to pull a message from a stream. Error is as follows: {}".format(str(e)))
83
+ logger.error("Due to the previous error, system will pause 10 seconds. System will then attempt to pull the message from "
84
+ "the stream again.")
85
+ time.sleep(10)
86
+ pubsub_client = pubsub_service.get_client(self.config)
87
+
88
+ def listen_async(self, on_message_callback, subscription_id=""):
89
+ def ack_message_and_callback(message):
90
+ pubsub_msg = json.loads(message.data)
91
+ logger.info("Received news message with ID: {}".format(
92
+ pubsub_msg['data'][0]['id']))
93
+ news_msg = pubsub_msg['data'][0]['attributes']
94
+ on_message_callback(news_msg, subscription_id)
95
+ message.ack()
96
+
97
+ pubsub_client = pubsub_service.get_client(self.config)
98
+
99
+ subscription_id = subscription_id or self.config.subscription()
100
+
101
+ if not subscription_id:
102
+ raise Exception(
103
+ 'No subscription specified. You must specify the subscription ID either through an environment variable, a config file or '
104
+ 'by passing the value to the method.')
105
+
106
+ streaming_credentials = credentials_service.fetch_credentials(
107
+ self.config)
108
+ subscription_path = pubsub_client.subscription_path(
109
+ streaming_credentials['project_id'], subscription_id)
110
+ subscription = pubsub_client.subscribe(
111
+ subscription_path, callback=ack_message_and_callback)
112
+ logger.info(
113
+ 'Listeners for subscriptions have been configured, set and await message arrival.')
114
+ return subscription
@@ -5,7 +5,7 @@ import requests
5
5
 
6
6
 
7
7
  def fetch_credentials(config):
8
- response = _get_requests().get(config.get_uri_context() + '/accounts/streaming-credentials',
8
+ response = _get_requests().get(config.get_uri_context() + '/sns-accounts/streaming-credentials',
9
9
  headers=config.get_headers())
10
10
 
11
11
  if response.status_code == 401: