|
| 1 | +# TOPCODER NOTIFICATIONS - CONSUMER VERIFICATION |
| 2 | + |
| 3 | +## Local Kafka setup |
| 4 | + |
| 5 | +- `http://kafka.apache.org/quickstart` contains details to setup and manage Kafka server, |
| 6 | + below provides details to setup Kafka server in Mac, Windows will use bat commands in bin/windows instead |
| 7 | +- download kafka at `https://www.apache.org/dyn/closer.cgi?path=/kafka/1.1.0/kafka_2.11-1.1.0.tgz` |
| 8 | +- extract out the downloaded tgz file |
| 9 | +- go to the extracted directory kafka_2.11-0.11.0.1 |
| 10 | +- start ZooKeeper server: |
| 11 | + `bin/zookeeper-server-start.sh config/zookeeper.properties` |
| 12 | +- use another terminal, go to same directory, start the Kafka server: |
| 13 | + `bin/kafka-server-start.sh config/server.properties` |
| 14 | +- note that the zookeeper server is at localhost:2181, and Kafka server is at localhost:9092 |
| 15 | +- use another terminal, go to same directory, create topics: |
| 16 | +``` |
| 17 | +bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic notifications.community.challenge.created |
| 18 | +bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic notifications.community.challenge.phasewarning |
| 19 | +``` |
| 20 | + |
| 21 | +- verify that the topic is created: |
| 22 | +``` |
| 23 | +bin/kafka-topics.sh --list --zookeeper localhost:2181 |
| 24 | +``` |
| 25 | + it should list out the created topics |
| 26 | + |
| 27 | +- run producer and then write some message into the console to send to the `notifications.community.challenge.created` topic: |
| 28 | +``` |
| 29 | +bin/kafka-console-producer.sh --broker-list localhost:9092 --topic notifications.community.challenge.created |
| 30 | +``` |
| 31 | +- In the console, write some message, one message per line: |
| 32 | +E.g. |
| 33 | +``` |
| 34 | +{ "topic": "notifications.community.challenge.created", "originator": "tc-direct", "timestamp": "2018-02-16T00:00:00", "mime-type": "application/json", "payload": { "challengeId": 30054674, "challengeTitle": "test", "challengeUrl": "http://www.topcoder.com/123", "userId": 8547899, "initiatorUserId": 123, "skills": ["dotnet", "xcode"] } } |
| 35 | +``` |
| 36 | + |
| 37 | +- optionally, use another terminal, go to same directory, start a consumer to view the messages: |
| 38 | +``` |
| 39 | +bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic notifications.community.challenge.created --from-beginning |
| 40 | +``` |
| 41 | + |
| 42 | + |
| 43 | +## Local deployment |
| 44 | + |
| 45 | +- start local Kafka, start local PostgreSQL db, create an empty database `notification` |
| 46 | +- set some config params via env as below, use `set` instead of `export` for windows OS, |
| 47 | + instead, you may set them via `config/default.js`, modify the DATABASE_URL according to your setup db: |
| 48 | +``` |
| 49 | +export LOG_LEVEL=debug |
| 50 | +export DATABASE_URL=postgres://postgres:123456@localhost:5432/notification |
| 51 | +export KAFKA_URL=localhost:9092 |
| 52 | +export KAFKA_GROUP_ID=tc-notifications |
| 53 | +export ENV=test |
| 54 | + |
| 55 | + |
| 56 | +``` |
| 57 | + |
| 58 | +- to override TC API base URLs to use mock APIs, it is not needed if mock APIs are not used: |
| 59 | +``` |
| 60 | +export TC_API_V3_BASE_URL=http://localhost:4000/v3 |
| 61 | +export TC_API_V4_BASE_URL=http://localhost:4000/v4 |
| 62 | +export TC_API_V5_BASE_URL=http://localhost:4000/v5 |
| 63 | +``` |
| 64 | + |
| 65 | +- set M2M config params: |
| 66 | +``` |
| 67 | +export AUTH0_CLIENT_ID=dummy |
| 68 | +export AUTH0_CLIENT_SECRET=dummy |
| 69 | +export AUTH0_URL=dummy |
| 70 | +export AUTH0_AUDIENCE=dummy |
| 71 | +``` |
| 72 | + |
| 73 | +- install dependencies `npm i` |
| 74 | +- run code lint check `npm run lint` |
| 75 | +- fix some lint errors `npm run lint:fix` |
| 76 | +- create db tables if not present `node test/init-db`, this is needed only for local test, in production the tables are already present |
| 77 | +- start notification consumer `npm run startConsumer` |
| 78 | + |
| 79 | + |
| 80 | +## Verification |
| 81 | + |
| 82 | +- Run Kafka console producer to write message to topic `notifications.community.challenge.created`: |
| 83 | + |
| 84 | +``` |
| 85 | +bin/kafka-console-producer.sh --broker-list localhost:9092 --topic notifications.community.challenge.created |
| 86 | +``` |
| 87 | + |
| 88 | +- Write message of challenge created: |
| 89 | + |
| 90 | +``` |
| 91 | +{ "topic": "notifications.community.challenge.created", "originator": "tc-direct", "timestamp": "2018-02-16T00:00:00", "mime-type": "application/json", "payload": { "challengeId": 30054674, "challengeTitle": "test", "challengeUrl": "http://www.topcoder.com/123", "userId": 8547899, "initiatorUserId": 123, "skills": ["dotnet", "xcode"] } } |
| 92 | +``` |
| 93 | + |
| 94 | +- You will see logging in the app console: |
| 95 | + |
| 96 | +``` |
| 97 | +info: Run handler handleChallengeCreated |
| 98 | +... |
| 99 | +verbose: Searched users: ... |
| 100 | +... |
| 101 | +info: Successfully sent notifications.action.email.connect.project.notifications.generic event with body ... to bus api |
| 102 | +... |
| 103 | +error: Failed to send email to user id: 5, handle: handle5 |
| 104 | +... |
| 105 | +info: Saved 8 notifications for users: 1, 2, 3, 4, 5, 6, 7, 8 |
| 106 | +info: Handler handleChallengeCreated was run successfully |
| 107 | +``` |
| 108 | + |
| 109 | + |
| 110 | +- Run Kafka console producer to write message to topic `notifications.community.challenge.phasewarning`: |
| 111 | + |
| 112 | +``` |
| 113 | +bin/kafka-console-producer.sh --broker-list localhost:9092 --topic notifications.community.challenge.phasewarning |
| 114 | +``` |
| 115 | + |
| 116 | +- Write message of challenge phase warning: |
| 117 | + |
| 118 | +``` |
| 119 | +{ "topic": "notifications.community.challenge.phasewarning", "originator": "tc-autopilot", "timestamp": "2018-02-16T00:00:00", "mime-type": "application/json", "payload": { "challengeId": 30054674, "challengeTitle": "test", "challengeUrl": "http://www.topcoder.com/123", "phase": "Submission", "remainingTime": 12345, "userId": 8547899, "initiatorUserId": 123 } } |
| 120 | +``` |
| 121 | + |
| 122 | +- You will see logging in the app console: |
| 123 | + |
| 124 | +``` |
| 125 | +info: Run handler handleChallengePhaseWarning |
| 126 | +... |
| 127 | +verbose: Searched users: ... |
| 128 | +... |
| 129 | +info: Successfully sent notifications.action.email.connect.project.notifications.generic event with body ... to bus api |
| 130 | +... |
| 131 | +error: Failed to send email to user id: 5, handle: handle5 |
| 132 | +... |
| 133 | +info: Saved 8 notifications for users: 1, 2, 3, 4, 5, 6, 7, 8 |
| 134 | +info: Handler handleChallengePhaseWarning was run successfully |
| 135 | +``` |
| 136 | + |
| 137 | + |
| 138 | +- Write message of challenge retrieved with error: |
| 139 | + |
| 140 | +``` |
| 141 | +{ "topic": "notifications.community.challenge.phasewarning", "originator": "tc-autopilot", "timestamp": "2018-02-16T00:00:00", "mime-type": "application/json", "payload": { "challengeId": 1111, "challengeTitle": "test", "challengeUrl": "http://www.topcoder.com/123", "phase": "Submission", "remainingTime": 12345, "userId": 8547899, "initiatorUserId": 123 } } |
| 142 | +``` |
| 143 | + |
| 144 | +- You will see logging in the app console: |
| 145 | + |
| 146 | +``` |
| 147 | +info: Run handler handleChallengePhaseWarning |
| 148 | +... |
| 149 | +error: Handler handleChallengePhaseWarning failed |
| 150 | +... |
| 151 | +error: { Error: Internal Server Error ... |
| 152 | +``` |
| 153 | + |
| 154 | + |
| 155 | +- Write message of challenge which is not found: |
| 156 | + |
| 157 | +``` |
| 158 | +{ "topic": "notifications.community.challenge.phasewarning", "originator": "tc-autopilot", "timestamp": "2018-02-16T00:00:00", "mime-type": "application/json", "payload": { "challengeId": 2222, "challengeTitle": "test", "challengeUrl": "http://www.topcoder.com/123", "phase": "Submission", "remainingTime": 12345, "userId": 8547899, "initiatorUserId": 123 } } |
| 159 | +``` |
| 160 | + |
| 161 | +- You will see logging in the app console: |
| 162 | + |
| 163 | +``` |
| 164 | +info: Run handler handleChallengePhaseWarning |
| 165 | +... |
| 166 | +error: Handler handleChallengePhaseWarning failed |
| 167 | +... |
| 168 | +error: { Error: Not Found ... |
| 169 | +``` |
| 170 | + |
| 171 | + |
| 172 | +- Write message of challenge of id 3333: |
| 173 | + |
| 174 | +``` |
| 175 | +{ "topic": "notifications.community.challenge.phasewarning", "originator": "tc-autopilot", "timestamp": "2018-02-16T00:00:00", "mime-type": "application/json", "payload": { "challengeId": 3333, "challengeTitle": "test", "challengeUrl": "http://www.topcoder.com/123", "phase": "Submission", "remainingTime": 12345, "userId": 8547899, "initiatorUserId": 123 } } |
| 176 | +``` |
| 177 | + |
| 178 | +- You will see logging in the app console: |
| 179 | + |
| 180 | +``` |
| 181 | +info: Run handler handleChallengePhaseWarning |
| 182 | +... |
| 183 | +error: Handler handleChallengePhaseWarning failed |
| 184 | +... |
| 185 | +error: { Error: Internal Server Error ... |
| 186 | +... { message: 'there is some error' } ... |
| 187 | +... Error: cannot GET /v3/members/_search?query=handle:%22handle1%22%20OR%20handle:%22handle2%22%20OR%20handle:%22handle3%22&offset=0&limit=5&fields=userId,email,handle,firstName,lastName,photoURL,status (500) ... |
| 188 | +... |
| 189 | +``` |
| 190 | + |
| 191 | + |
| 192 | +- You may write some invalid messages like below: |
| 193 | + |
| 194 | +``` |
| 195 | +{ "topic": "notifications.community.challenge.phasewarning", "originator": "tc-autopilot", "timestamp": "invalid", "mime-type": "application/json", "payload": { "challengeId": 30054674, "challengeTitle": "test", "challengeUrl": "http://www.topcoder.com/123", "phase": "Submission", "remainingTime": 12345, "userId": 8547899, "initiatorUserId": 123 } } |
| 196 | +``` |
| 197 | + |
| 198 | +``` |
| 199 | +{ "topic": "notifications.community.challenge.phasewarning", "originator": "tc-autopilot", "timestamp": "2018-02-16T00:00:00", "mime-type": "application/json", "payload": { "challengeTitle": "test", "challengeUrl": "http://www.topcoder.com/123", "phase": "Submission", "remainingTime": 12345, "userId": 8547899, "initiatorUserId": 123 } } |
| 200 | +``` |
| 201 | + |
| 202 | +``` |
| 203 | +{ [ xyz |
| 204 | +``` |
| 205 | + |
| 206 | +- You will see error logging in the app console. |
| 207 | + |
| 208 | +- Use some PostgreSQL client to connect to the database, e.g. you may use the PostgreSQL's built-in client psql to connect to the database: `psql -U postgres` |
| 209 | + |
| 210 | +- connect to database: `\c notification` |
| 211 | + |
| 212 | +- select notifications: `select * from "Notifications";` |
| 213 | + |
| 214 | +- you will see notification records: |
| 215 | + |
| 216 | +``` |
| 217 | + 1 | 23154497 | notifications.community.challenge.created | {"skills": ["dotnet", "xcode"], "userId": 8547899, "challengeId": 30054522, "challengeUrl": "http://www.topcoder.com/123", "challengeTitle": "test", "initiatorUserId": 123} | f | f | | 2019-04-01 19:49:08.232+08 | 2019-04-01 19:49:08.232+08 |
| 218 | + 2 | 294446 | notifications.community.challenge.created | {"skills": ["dotnet", "xcode"], "userId": 8547899, "challengeId": 30054522, "challengeUrl": "http://www.topcoder.com/123", "challengeTitle": "test", "initiatorUserId": 123} | f | f | | 2019-04-01 19:49:08.232+08 | 2019-04-01 19:49:08.232+08 |
| 219 | + ... |
| 220 | +``` |
| 221 | + |
0 commit comments