diff --git a/.circleci/config.yml b/.circleci/config.yml index 6088a790..68ccdc8b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,20 @@ version: 2 jobs: + test_dashboard_server: + machine: + image: ubuntu-1604:202007-01 + steps: + - checkout + - run: + command: ./test.sh dashboard-server --is-ci + test_dean: + machine: + image: ubuntu-1604:202007-01 + steps: + - checkout + - run: + command: ./test.sh dean --is-ci test_dinersclub: machine: image: ubuntu-1604:202007-01 @@ -15,6 +29,27 @@ jobs: - checkout - run: command: ./test.sh formcentral --is-ci + test_linksniffer: + machine: + image: ubuntu-1604:202007-01 + steps: + - checkout + - run: + command: ./test.sh linksniffer --is-ci + test_replybot: + machine: + image: ubuntu-1604:202007-01 + steps: + - checkout + - run: + command: ./test.sh replybot --is-ci + test_scribble: + machine: + image: ubuntu-1604:202007-01 + steps: + - checkout + - run: + command: ./test.sh scribble --is-ci test_e2e: machine: image: ubuntu-1604:202007-01 @@ -46,7 +81,12 @@ workflows: version: 2 test: jobs: + - test_dashboard_server + - test_dean - test_dinersclub - test_formcentral + - test_linksniffer + - test_replybot + - test_scribble - test_e2e: context: secrets diff --git a/README.md b/README.md index 5866a554..70311120 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,44 @@ helm install fly vlab -f values/production.yaml ## Development +### Testing locally + +Fly is made up of multiple services, where each service is responsible for a specific _scope of work_. + +For convenience, we have created tools to make it easy to add features and bug fixes to services, while maintaining the expected behaviors of previous features. We took inspiration from test-driven-development to enable developers to write new business logic while testing continuously in a hot-reload fashion. This closed feedback loop allows early detection of potential problems. + +Because services are written using two programming languages (`javascript` and `go`), the test suite naturally behaves differently for each of them (we use `mocha` for `javascript` and `testing` for `go`), but they are _initialized_ in the same way. + +For services written in `javascript` or `go`, you can start the local test suite by executing in your terminal: + +``` +./test.sh {NAME_OF_SERVICE} +``` + +where `{NAME_OF_SERVICE}` corresponds to the name of the service (the name of the directory). For example, if you want to run the `scribble` test suite, you can type in your terminal: + +``` +./test.sh scribble +``` + +The `scribble` service is written in `go`, but you can use any service name, even those written in `javascript`. + +Once it's running, you can edit the service code and the test suite will run all the tests for that service every time you save your changes. _How cool!_ + +#### Running a single test + +Sometimes, it's convinient to run only one test at the time. + +For tests executed by `mocha`, you can add `.only()` to the test. For more information on `only()`, visit https://mochajs.org/#exclusive-tests. + +For tests written in `go`, you can add the name of the test that you want to run exclusively, to the command that _initializes_ the test suite. For example, if the name of the test is `TestCreateUserReturnsSuccess`, the command you will execute in your terminal will look like this: + +``` +./test.sh scribble TestCreateUserReturnsSuccess +``` + +### Testing inside Kubernetes + Make sure you have KIND installed. Then run: @@ -22,3 +60,4 @@ Then run: cd devops ./dev-cluster.sh ``` + diff --git a/dashboard-server/Dockerfile b/dashboard-server/Dockerfile index c0497a80..c6100294 100644 --- a/dashboard-server/Dockerfile +++ b/dashboard-server/Dockerfile @@ -1,12 +1,12 @@ FROM node:10-stretch -WORKDIR /usr/src/app +RUN mkdir /app +WORKDIR /app -COPY package.json . -RUN npm i - -COPY . . +COPY package.json /app +RUN npm install +COPY . /app EXPOSE 3000 -CMD [ "npm", "start"] +CMD [ "npm", "start" ] diff --git a/dashboard-server/config/index.js b/dashboard-server/config/index.js index 6cdbea31..bd916705 100644 --- a/dashboard-server/config/index.js +++ b/dashboard-server/config/index.js @@ -5,7 +5,6 @@ const jwks = require('jwks-rsa'); const envVarsSchema = joi .object({ - NODE_ENV: joi.string().allow(['development', 'production', 'test']), API_VERSION: joi.number(), AUTH0_HOST: joi.string(), DB_USER: joi.string(), @@ -31,12 +30,7 @@ if (error) { throw new Error(`Config validation error: ${error.message}`); } -const isTest = () => envVars.NODE_ENV === 'test'; - const config = { - ENV: envVars.NODE_ENV, - IS_DEVELOPMENT: envVars.NODE_ENV === 'development', - IS_TEST: isTest(), FORMCENTRAL: { url: envVars.FORMCENTRAL_URL, }, @@ -69,11 +63,11 @@ const config = { secret: envVars.AUTH0_DASHBOARD_SECRET }, DATABASE_CONFIG: { - user: isTest() ? 'root' : envVars.DB_USER || 'postgres', - host: isTest() ? 'localhost' : envVars.DB_HOST || 'localhost', - database: isTest() ? 'chatroach' : envVars.DB_DATABASE || 'postgres', - password: isTest() ? undefined : envVars.DB_PASSWORD || undefined, - port: isTest() ? 5433 : envVars.DB_PORT || 5432, + user: envVars.DB_USER, + host: envVars.DB_HOST, + database: envVars.DB_DATABASE, + password: envVars.DB_PASSWORD, + port: envVars.DB_PORT, }, }; diff --git a/dashboard-server/package.json b/dashboard-server/package.json index 39f2095c..9efd4b30 100644 --- a/dashboard-server/package.json +++ b/dashboard-server/package.json @@ -9,7 +9,7 @@ "lint": "eslint .", "precommit": "npm run lint", "start": "node index.js", - "test": "NODE_ENV=test mocha --colors --timeout 5000 './{,!(node_modules)/**}/*.test.js'" + "test": "mocha --colors --timeout 5000 './{,!(node_modules)/**}/*.test.js'" }, "repository": { "type": "git", diff --git a/dashboard-server/queries/responses/response.queries.js b/dashboard-server/queries/responses/response.queries.js index ccaaaeff..cb5210c9 100644 --- a/dashboard-server/queries/responses/response.queries.js +++ b/dashboard-server/queries/responses/response.queries.js @@ -13,7 +13,10 @@ async function all() { SELECT DISTINCT ON (1) userid, timestamp AS last_timestamp, response AS last_response, surveyid FROM responses ORDER BY 1,2 DESC - ) l USING (userid)`; + ) l + USING (userid) + ORDER BY first_timestamp DESC + `; const { rows } = await this.query(GET_ALL); return rows; } diff --git a/dashboard-server/queries/responses/response.test.js b/dashboard-server/queries/responses/response.test.js index 62c942c7..c906bb15 100644 --- a/dashboard-server/queries/responses/response.test.js +++ b/dashboard-server/queries/responses/response.test.js @@ -1,86 +1,94 @@ const { Pool } = require('pg'); require('chai').should(); require('mocha'); +const axios = require('axios'); -const model = require('./response.queries'); +const responseModel = require('./response.queries'); +const surveyModel = require('../surveys/survey.queries'); +const userModel = require('../users/user.queries'); const { DATABASE_CONFIG } = require('../../config'); describe('Response queries', () => { + let pool; let Response; - let vlabPool; + let Survey; + let User; before(async () => { - let pool = new Pool({ - user: 'postgres', - host: 'localhost', - database: 'postgres', - password: undefined, - port: 5432, - }); + pool = new Pool(DATABASE_CONFIG); + Response = responseModel.queries(pool); + Survey = surveyModel.queries(pool); + User = userModel.queries(pool); + }); - try { - await pool.query('CREATE DATABASE vlab_dashboard_test'); - } catch (e) {} + beforeEach(async () => { + await axios.get('http://system/resetdb'); + }); - vlabPool = new Pool(DATABASE_CONFIG); + describe('.all()', () => { + it('should get the list of the first and last responses for each user', async () => { + const user1 = await User.create({ + token: 'AAAA', + email: 'test1@vlab.com', + }); - await vlabPool.query( - `CREATE TABLE responses( - parent_surveyid UUID NOT NULL, - parent_shortcode INT NOT NULL, - surveyid UUID NOT NULL, - shortcode INT NOT NULL, - flowid INT NOT NULL, - userid VARCHAR NOT NULL, - question_ref VARCHAR NOT NULL, - question_idx INT NOT NULL, - question_text VARCHAR NOT NULL, - response VARCHAR NOT NULL, - seed INT NOT NULL, - timestamp TIMESTAMPTZ NOT NULL, - PRIMARY KEY (userid, timestamp) - )`, - ); - await vlabPool.query('DELETE FROM responses'); + const user2 = await User.create({ + token: 'BBBB', + email: 'test2@vlab.com', + }); - Response = model.queries(vlabPool); - }); + const user3 = await User.create({ + token: 'CCCC', + email: 'test3@vlab.com', + }); - afterEach(async () => { - await vlabPool.query('DELETE FROM responses'); - }); + const survey1 = await Survey.create({ + created: new Date(), + formid: 'DDD', + form: '{"form": "form detail 1"}', + shortcode: 123, + userid: user1.id, + title: 'New User Title 1', + metadata: '{}', + survey_name: "test 1", + translation_conf: '{}', + }); - after(async () => { - await vlabPool.query('DROP TABLE responses'); - }); + const survey2 = await Survey.create({ + created: new Date(), + formid: 'EEE', + form: '{"form": "form detail 2"}', + shortcode: 567, + userid: user2.id, + title: 'New User Title 2', + metadata: '{}', + survey_name: "test 2", + translation_conf: '{}', + }); - describe('.all()', () => { - it('should get the list of the first and last responses for each user', async () => { - const MOCK_QUERY = `INSERT INTO responses(parent_surveyid, parent_shortcode, surveyid, shortcode, flowid, userid, question_ref, question_idx, question_text, response, seed, timestamp) - VALUES - ('b8b960ca-3c0d-4a64-a058-2140ee89596b', '101', 'b8b960ca-3c0d-4a64-a058-2140ee89596b', '101', 100001, '124', 'ref', 10, 'text', '{ "text": "last" }', '6789', current_date + interval '14 hour') - ,('f5de09c8-f2c3-49ac-847d-33c8bf5be427', '202', 'f5de09c8-f2c3-49ac-847d-33c8bf5be427', '202', 100003, '123', 'ref', 10, 'text', '{ "text": "last" }', '6789', date '2019-04-18' + interval '12 hour') - ,('b8b960ca-3c0d-4a64-a058-2140ee89596b', '101', 'b8b960ca-3c0d-4a64-a058-2140ee89596b', '101', 100004, '124', 'ref', 10, 'text', '{ "text": "first" }', '6789', current_date + interval '10 hour') - ,('f5de09c8-f2c3-49ac-847d-33c8bf5be427', '202', 'f5de09c8-f2c3-49ac-847d-33c8bf5be427', '202', 100005, '123', 'ref', 10, 'text', '{ "text": "first" }', '6789', date '2019-04-18' + interval '8 hour') - ,('f5de09c8-f2c3-49ac-847d-33c8bf5be427', '202', 'f5de09c8-f2c3-49ac-847d-33c8bf5be427', '202', 100003, '125', 'ref', 10, 'text', '{ "text": "last" }', '6789', date '2019-04-18' + interval '12 hour') - ,('b8b960ca-3c0d-4a64-a058-2140ee89596b', '101', 'b8b960ca-3c0d-4a64-a058-2140ee89596b', '101', 100004, '125', 'ref', 10, 'text', '{ "text": "first" }', '6789', date '2019-04-18' + interval '10 hour') - ,('f5de09c8-f2c3-49ac-847d-33c8bf5be427', '202', 'f5de09c8-f2c3-49ac-847d-33c8bf5be427', '202', 100005, '125', 'ref', 10, 'text', '{ "text": "first" }', '6789', date '2019-04-18' + interval '8 hour') - ,('b8b960ca-3c0d-4a64-a058-2140ee89596b', '101', 'b8b960ca-3c0d-4a64-a058-2140ee89596b', '101', 100006, '124', 'ref', 10, 'text', '{ "text": "middle" }', '6789', current_date + interval '12 hour')`; + const MOCK_QUERY = ` + INSERT INTO responses(parent_surveyid, parent_shortcode, surveyid, shortcode, flowid, userid, question_ref, question_idx, question_text, response, seed, timestamp) + VALUES + ('${survey1.id}', '${survey1.shortcode}', '${survey1.id}', '${survey1.shortcode}', 100001, '${user1.id}', 'ref', 10, 'text', '{ "text": "last" }', '6789', '2019-05-29T14:00:01.00Z'), + ('${survey2.id}', '${survey2.shortcode}', '${survey2.id}', '${survey2.shortcode}', 100003, '${user2.id}', 'ref', 10, 'text', '{ "text": "last" }', '6789', '2010-05-29T12:00:01.00Z'), + ('${survey1.id}', '${survey1.shortcode}', '${survey1.id}', '${survey1.shortcode}', 100004, '${user1.id}', 'ref', 10, 'text', '{ "text": "first" }', '6789', '2019-05-29T10:20:01.00Z'), + ('${survey2.id}', '${survey2.shortcode}', '${survey2.id}', '${survey2.shortcode}', 100005, '${user2.id}', 'ref', 10, 'text', '{ "text": "first" }', '6789', '2010-05-29T08:00:01.00Z'), + ('${survey2.id}', '${survey2.shortcode}', '${survey2.id}', '${survey2.shortcode}', 100003, '${user3.id}', 'ref', 10, 'text', '{ "text": "last" }', '6789', '2010-05-29T12:00:01.00Z'), + ('${survey1.id}', '${survey1.shortcode}', '${survey1.id}', '${survey1.shortcode}', 100004, '${user3.id}', 'ref', 10, 'text', '{ "text": "first" }', '6789', '2010-05-29T10:00:01.00Z'), + ('${survey2.id}', '${survey2.shortcode}', '${survey2.id}', '${survey2.shortcode}', 100005, '${user3.id}', 'ref', 10, 'text', '{ "text": "first" }', '6789', '2010-05-29T08:00:01.00Z'), + ('${survey1.id}', '${survey1.shortcode}', '${survey1.id}', '${survey1.shortcode}', 100006, '${user1.id}', 'ref', 10, 'text', '{ "text": "middle" }', '6789', '2019-05-29T12:00:01.00Z') + `; - await vlabPool.query(MOCK_QUERY); + await pool.query(MOCK_QUERY); const responses = await Response.all(); responses[0].first_response.should.equal('{ "text": "first" }'); responses[0].last_response.should.equal('{ "text": "last" }'); - responses[0].surveyid.should.equal( - 'f5de09c8-f2c3-49ac-847d-33c8bf5be427', - ); + responses[0].surveyid.should.equal(survey1.id); responses[1].first_response.should.equal('{ "text": "first" }'); responses[1].last_response.should.equal('{ "text": "last" }'); - responses[1].surveyid.should.equal( - 'b8b960ca-3c0d-4a64-a058-2140ee89596b', - ); + responses[1].surveyid.should.equal(survey2.id); }); }); }); diff --git a/dashboard-server/queries/surveys/survey.test.js b/dashboard-server/queries/surveys/survey.test.js index 97df9535..7600b93b 100644 --- a/dashboard-server/queries/surveys/survey.test.js +++ b/dashboard-server/queries/surveys/survey.test.js @@ -1,6 +1,7 @@ /* eslint-disable no-unused-expressions */ const { Pool } = require('pg'); const chai = require('chai'); +const axios = require('axios'); chai.should(); require('mocha'); @@ -13,64 +14,16 @@ const { DATABASE_CONFIG } = require('../../config'); describe('Survey queries', () => { let Survey; let User; - let vlabPool; + let pool; before(async () => { - let pool = new Pool({ - user: 'root', - host: 'localhost', - database: 'defaultdb', - password: undefined, - port: 5432, - }); - - try { - await pool.query('CREATE DATABASE chatroach;'); - } catch (e) {} - - vlabPool = new Pool(DATABASE_CONFIG); - - await vlabPool.query( - `CREATE TABLE chatroach.users( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - token VARCHAR NOT NULL, - email VARCHAR NOT NULL UNIQUE - )`, - ); - - await vlabPool.query( - `CREATE TABLE chatroach.facebook_pages( - pageid VARCHAR PRIMARY KEY, - userid UUID REFERENCES chatroach.users(id) ON DELETE CASCADE - );`, - ); - - await vlabPool.query( - `CREATE TABLE chatroach.surveys( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - created TIMESTAMPTZ NOT NULL, - formid VARCHAR NOT NULL, - form VARCHAR NOT NULL, - messages VARCHAR, - shortcode INT4 NOT NULL, - title VARCHAR NOT NULL, - userid UUID NOT NULL REFERENCES chatroach.users(id) ON DELETE CASCADE - )`, - ); - - User = userModel.queries(vlabPool); - Survey = surveyModel.queries(vlabPool); + pool = new Pool(DATABASE_CONFIG); + User = userModel.queries(pool); + Survey = surveyModel.queries(pool); }); - afterEach(async () => { - await vlabPool.query('DELETE FROM users'); - await vlabPool.query('DELETE FROM surveys'); - }); - - after(async () => { - await vlabPool.query('DROP TABLE users CASCADE'); - await vlabPool.query('DROP TABLE facebook_pages'); - await vlabPool.query('DROP TABLE surveys'); + beforeEach(async () => { + await axios.get('http://system/resetdb'); }); describe('.create()', () => { @@ -80,8 +33,6 @@ describe('Survey queries', () => { email: 'test@vlab.com', }; const newUser = await User.create(user); - - newUser.token.should.equal(user.token); newUser.email.should.equal(user.email); const survey = { @@ -92,11 +43,15 @@ describe('Survey queries', () => { shortcode: 123, userid: newUser.id, title: 'New User Title', + metadata: '{}', + survey_name: "test", + translation_conf: '{}', }; const newSurvey = await Survey.create(survey); + newSurvey.formid.should.equal('S8yR4'); newSurvey.form.should.equal('{"form": "form detail"}'); - newSurvey.shortcode.should.equal(123); + newSurvey.shortcode.should.equal('123'); newSurvey.userid.should.equal(newUser.id); newSurvey.title.should.equal('New User Title'); }); @@ -104,11 +59,11 @@ describe('Survey queries', () => { describe('.retrieve()', () => { it('should insert a new survey and return the newly created record', async () => { - const user2 = { + const user = { token: 'dasfYoykme73Jz1c93d1xPws77GzuhNU0f1wu1pHeh91', email: 'test2@vlab.com', }; - const newUser = await User.create(user2); + const newUser = await User.create(user); const survey = { created: new Date(), @@ -118,6 +73,9 @@ describe('Survey queries', () => { shortcode: 231, userid: newUser.id, title: 'Second Survey', + metadata: '{}', + survey_name: "test", + translation_conf: '{}', }; await Survey.create(survey); @@ -129,6 +87,9 @@ describe('Survey queries', () => { shortcode: 123, userid: newUser.id, title: 'Other survey', + metadata: '{}', + survey_name: "test", + translation_conf: '{}', }; await Survey.create(survey2); diff --git a/dashboard-server/queries/users/user.test.js b/dashboard-server/queries/users/user.test.js index 2215b6e7..84ef63f0 100644 --- a/dashboard-server/queries/users/user.test.js +++ b/dashboard-server/queries/users/user.test.js @@ -1,6 +1,7 @@ const { Pool } = require('pg'); require('chai').should(); require('mocha'); +const axios = require('axios'); const model = require('./user.queries'); @@ -8,41 +9,15 @@ const { DATABASE_CONFIG } = require('../../config'); describe('User queries', () => { let User; - let vlabPool; + let pool; before(async () => { - let pool = new Pool({ - user: 'root', - host: 'localhost', - database: 'default', - password: undefined, - port: 5432, - }); - - try { - await pool.query('CREATE DATABASE chatroach'); - } catch (e) {} - - vlabPool = new Pool(DATABASE_CONFIG); - - await vlabPool.query( - `CREATE TABLE chatroach.users( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - token VARCHAR NOT NULL, - email VARCHAR NOT NULL UNIQUE - );`, - ); - await vlabPool.query('DELETE FROM users'); - - User = model.queries(vlabPool); - }); - - afterEach(async () => { - await vlabPool.query('DELETE FROM users'); + pool = new Pool(DATABASE_CONFIG); + User = model.queries(pool); }); - after(async () => { - await vlabPool.query('DROP TABLE users CASCADE'); + beforeEach(async () => { + await axios.get('http://system/resetdb'); }); describe('.create()', () => { @@ -52,25 +27,7 @@ describe('User queries', () => { email: 'test@vlab.com', }; const newUser = await User.create(user); - newUser.token.should.equal(user.token); - newUser.email.should.equal(user.email); - }); - }); - - describe('.update()', () => { - it('should update a user or create a new one', async () => { - const user = { - token: '8eQ9ZYXw2Vsb16aC7aKzXFqzE7oamzKQttaHnCNHoRu8', - email: 'test@vlab.com', - }; - const newUser = await User.update(user); - newUser.token.should.equal(user.token); newUser.email.should.equal(user.email); - - user.token = 'HxpnYoykme73Jz1c9DdAxPws77GzH9jLqE1wu1piSqJj'; - const userUpdated = await User.update(user); - userUpdated.token.should.equal(user.token); - userUpdated.email.should.equal(user.email); }); }); @@ -82,7 +39,6 @@ describe('User queries', () => { }; await User.create(user); const userFromDb = await User.user(user); - userFromDb.token.should.equal(user.token); userFromDb.email.should.equal(user.email); }); }); diff --git a/dashboard-server/test.yaml b/dashboard-server/test.yaml new file mode 100644 index 00000000..2cf57bcd --- /dev/null +++ b/dashboard-server/test.yaml @@ -0,0 +1,70 @@ +version: '3' + +services: + main: + depends_on: + - system + image: ${APP_NAME}_dev + build: . + environment: + DB_DATABASE: chatroach + DB_HOST: cockroachdb + DB_PORT: 26257 + DB_USER: root + command: | + sh -c ' + npm install + if [ "${ARG}" = "--is-ci" ] + then + npm test + exit + fi + npm run test -- --watch + ' + volumes: + - ./:/app + networks: + - fly + system: + build: + context: ../system + environment: + CHATBASE_DATABASE: chatroach + CHATBASE_HOST: cockroachdb + CHATBASE_PORT: 26257 + CHATBASE_USER: root + PORT: 80 + command: go run . + ports: + - 80:80 + volumes: + - ../system:/app + networks: + - fly + initdb: + image: cockroachdb/cockroach:v20.1.4 + depends_on: + - cockroachdb + entrypoint: | + sh -c ' + /tools/wait-for-it.sh cockroachdb:26257 -t 60 + cat /migrations/* > /tmp/merged-latest.sql + cat /tmp/merged-latest.sql | ./cockroach sql --insecure --host cockroachdb + echo "set sql_safe_updates=false;" | ./cockroach sql --insecure --host cockroachdb + ' + volumes: + - ../devops:/tools + - ../devops/sql:/migrations + networks: + - fly + cockroachdb: + image: cockroachdb/cockroach:v20.1.4 + command: start --insecure + ports: + - 26257:26257 + networks: + - fly + +networks: + fly: + driver: bridge diff --git a/dean/.dockerignore b/dean/.dockerignore deleted file mode 100644 index 5b9b3947..00000000 --- a/dean/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -Dockerfile -values.yaml -chart/ \ No newline at end of file diff --git a/dean/.gitignore b/dean/.gitignore deleted file mode 100644 index 88f82ecc..00000000 --- a/dean/.gitignore +++ /dev/null @@ -1,27 +0,0 @@ - -# Created by https://www.toptal.com/developers/gitignore/api/go -# Edit at https://www.toptal.com/developers/gitignore?templates=go - -### Go ### -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Test binary, built with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Dependency directories (remove the comment below to include it) -# vendor/ - -### Go Patch ### -/vendor/ -/Godeps/ - -# End of https://www.toptal.com/developers/gitignore/api/go -.env diff --git a/dean/Dockerfile.dev b/dean/Dockerfile.dev new file mode 100644 index 00000000..7836ed31 --- /dev/null +++ b/dean/Dockerfile.dev @@ -0,0 +1,13 @@ +FROM golang:alpine + +RUN apk add --no-cache \ + gcc \ + libc-dev \ + npm + +RUN mkdir /app +COPY go.mod /app +WORKDIR /app + +RUN go mod download +RUN npm install -g nodemon diff --git a/dean/config.go b/dean/config.go new file mode 100644 index 00000000..8e8dec14 --- /dev/null +++ b/dean/config.go @@ -0,0 +1,32 @@ +package main + +import ( + "time" + + "github.com/caarlos0/env/v6" +) + +type Config struct { + DbName string `env:"CHATBASE_DATABASE,required"` + DbHost string `env:"CHATBASE_HOST,required"` + DbPort int `env:"CHATBASE_PORT,required"` + DbUser string `env:"CHATBASE_USER,required"` + Botserver string `env:"BOTSERVER_URL,required"` + Codes []string `env:"DEAN_FB_CODES,required" envSeparator:","` + ErrorTags []string `env:"DEAN_ERROR_TAGS,required" envSeparator:","` + ErrorInterval string `env:"DEAN_ERROR_INTERVAL,required"` + BlockedInterval string `env:"DEAN_BLOCKED_INTERVAL,required"` + RespondingInterval string `env:"DEAN_RESPONDING_INTERVAL,required"` + RespondingGrace string `env:"DEAN_RESPONDING_GRACE,required"` + Queries string `env:"DEAN_QUERIES,required"` + SendDelay time.Duration `env:"DEAN_SEND_DELAY,required"` + FollowUpMin string `env:"DEAN_FOLLOWUP_MIN,required"` + FollowUpMax string `env:"DEAN_FOLLOWUP_MAX,required"` +} + +func getConfig() *Config { + cfg := Config{} + err := env.Parse(&cfg) + handle(err) + return &cfg +} diff --git a/dean/dean.go b/dean/dean.go index 554284e0..f820062f 100644 --- a/dean/dean.go +++ b/dean/dean.go @@ -11,7 +11,6 @@ import ( "sync" "time" - "github.com/caarlos0/env/v6" "github.com/jackc/pgx/v4/pgxpool" ) @@ -41,25 +40,6 @@ func handle(err error) { } } -type Config struct { - Db string `env:"CHATBASE_DATABASE,required"` - User string `env:"CHATBASE_USER,required"` - Password string `env:"CHATBASE_PASSWORD,required"` - Host string `env:"CHATBASE_HOST,required"` - Port string `env:"CHATBASE_PORT,required"` - Botserver string `env:"BOTSERVER_URL,required"` - Codes []string `env:"DEAN_FB_CODES,required" envSeparator:","` - ErrorTags []string `env:"DEAN_ERROR_TAGS,required" envSeparator:","` - ErrorInterval string `env:"DEAN_ERROR_INTERVAL,required"` - BlockedInterval string `env:"DEAN_BLOCKED_INTERVAL,required"` - RespondingInterval string `env:"DEAN_RESPONDING_INTERVAL,required"` - RespondingGrace string `env:"DEAN_RESPONDING_GRACE,required"` - Queries string `env:"DEAN_QUERIES,required"` - SendDelay time.Duration `env:"DEAN_SEND_DELAY,required"` - FollowUpMin string `env:"DEAN_FOLLOWUP_MIN,required"` - FollowUpMax string `env:"DEAN_FOLLOWUP_MAX,required"` -} - func send(cfg *Config, client *http.Client, e *ExternalEvent) error { body, err := json.Marshal(e) @@ -96,8 +76,8 @@ func process(cfg *Config, ch <-chan *ExternalEvent) { } func getConn(cfg *Config) *pgxpool.Pool { - conString := fmt.Sprintf("postgresql://%s@%s:%s/%s?sslmode=disable", cfg.User, cfg.Host, cfg.Port, cfg.Db) - config, err := pgxpool.ParseConfig(conString) + con := fmt.Sprintf("postgresql://%s@%s:%d/%s?sslmode=disable", cfg.DbUser, cfg.DbHost, cfg.DbPort, cfg.DbName) + config, err := pgxpool.ParseConfig(con) handle(err) ctx := context.Background() @@ -124,10 +104,7 @@ func getQueries(cfg *Config, pool *pgxpool.Pool) []<-chan *ExternalEvent { } func main() { - cfg := &Config{} - err := env.Parse(cfg) - handle(err) - + cfg := getConfig() pool := getConn(cfg) defer pool.Close() diff --git a/dean/go.mod b/dean/go.mod index e6d9329e..481ef5f7 100644 --- a/dean/go.mod +++ b/dean/go.mod @@ -3,11 +3,8 @@ module github.com/vlab-research/dean go 1.15 require ( - github.com/caarlos0/env/v6 v6.3.0 - github.com/jackc/pgconn v1.6.4 - github.com/jackc/pgproto3/v2 v2.0.4 // indirect - github.com/jackc/pgx/v4 v4.8.1 - github.com/stretchr/testify v1.5.1 - golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + github.com/caarlos0/env/v6 v6.9.1 + github.com/jackc/pgconn v1.10.1 + github.com/jackc/pgx/v4 v4.14.1 + github.com/stretchr/testify v1.7.0 ) diff --git a/dean/go.sum b/dean/go.sum index a1ab7610..abda9fa7 100644 --- a/dean/go.sum +++ b/dean/go.sum @@ -1,6 +1,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/caarlos0/env/v6 v6.3.0 h1:PaqGnS5iHScZ5SnZNBPvQbA2VE/eMAwlp51mKGuEZLg= -github.com/caarlos0/env/v6 v6.3.0/go.mod h1:nXKfztzgWXH0C5Adnp+gb+vXHmMjKdBnMrSVSczSkiw= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/caarlos0/env/v6 v6.9.1 h1:zOkkjM0F6ltnQ5eBX6IPI41UP/KDGEK7rRPwGCNos8k= +github.com/caarlos0/env/v6 v6.9.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= @@ -9,9 +11,11 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= @@ -21,15 +25,17 @@ github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgO github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= -github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.6.4 h1:S7T6cx5o2OqmxdHaXLH1ZeD1SbI8jBznyYE9Ec0RCQ8= -github.com/jackc/pgconn v1.6.4/go.mod h1:w2pne1C2tZgP+TvjqLpOigGzNqjBgQW9dUw/4Chex78= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.10.1 h1:DzdIHIjG1AxGwoEEqS+mGsURyjt4enSmqzACXvVzOT8= +github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= @@ -38,35 +44,29 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.0.2 h1:q1Hsy66zh4vuNsajBUF2PNqfAMMfxU5mk594lPE9vjY= -github.com/jackc/pgproto3/v2 v2.0.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.0.4 h1:RHkX5ZUD9bl/kn0f9dYUWs1N7Nwvo1wwUYvKiR26Zco= -github.com/jackc/pgproto3/v2 v2.0.4/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5ns= +github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= -github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= -github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= -github.com/jackc/pgtype v1.4.2 h1:t+6LWm5eWPLX1H5Se702JSBcirq6uWa4jiG4wV1rAWY= -github.com/jackc/pgtype v1.4.2/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.9.1 h1:MJc2s0MFS8C3ok1wQTdQxWuXQcB6+HwAm5x1CzW7mf0= +github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= -github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= -github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= -github.com/jackc/pgx/v4 v4.8.1 h1:SUbCLP2pXvf/Sr/25KsuI4aTxiFYIvpfk4l6aTSdyCw= -github.com/jackc/pgx/v4 v4.8.1/go.mod h1:4HOLxrl8wToZJReD04/yB20GDwf4KBYETvlHciCnwW0= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.14.1 h1:71oo1KAGI6mXhLiTMn6iDFcp3e7+zon/capWjl2OEFU= +github.com/jackc/pgx/v4 v4.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.1 h1:PJAw7H/9hoWC4Kf3J8iNmL1SwA6E8vfsLqBiL+F6CtI= -github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.2.0 h1:DNDKdn/pDrWvDWyT2FYvpZVE81OAhWrjCv19I9n108Q= +github.com/jackc/puddle v1.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -79,15 +79,12 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -99,8 +96,8 @@ github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OK github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -109,33 +106,39 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -144,13 +147,19 @@ golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -158,18 +167,18 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/dean/queries_test.go b/dean/queries_test.go index 70dd3a76..cf6798b6 100644 --- a/dean/queries_test.go +++ b/dean/queries_test.go @@ -5,63 +5,34 @@ import ( "fmt" "testing" "time" + "net/http" "github.com/stretchr/testify/assert" ) const ( - surveySql = `drop table if exists surveys; - create table if not exists surveys( - userid VARCHAR NOT NULL, - shortcode VARCHAR NOT NULL, - messages_json JSON, - created TIMESTAMPTZ NOT NULL, - has_followup BOOL AS (messages_json->>'label.buttonHint.default' IS NOT NULL) STORED - ); - - drop table if exists credentials; - create table if not exists credentials( - userid VARCHAR NOT NULL, - entity VARCHAR NOT NULL, - key VARCHAR NOT NULL UNIQUE, - created TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, - details JSONB NOT NULL, - facebook_page_id VARCHAR AS (CASE WHEN entity = 'facebook_page' THEN details->>'id' ELSE NULL END) STORED, - UNIQUE(entity, key), - UNIQUE(facebook_page_id) - ); - ` - - pageInsertSql = `INSERT INTO credentials(entity, key, userid, details) VALUES ('facebook_page', ($1)->>'id', 'owner', $1)` - surveyInsertSql = `INSERT INTO surveys(userid, shortcode, created, messages_json) VALUES ('owner', $1, $2, $3);` - - stateSql = `drop table if exists states; - create table if not exists states( - userid VARCHAR NOT NULL, - pageid VARCHAR NOT NULL NOT NULL, - updated TIMESTAMPTZ NOT NULL, - current_state VARCHAR NOT NULL, - state_json JSON NOT NULL, - current_form VARCHAR AS (state_json->'forms'->>-1) STORED, - form_start_time TIMESTAMPTZ AS (CEILING((state_json->'md'->>'startTime')::INT/1000)::INT::TIMESTAMPTZ) STORED, - previous_with_token BOOL AS (state_json->'previousOutput'->>'token' IS NOT NULL) STORED, - previous_is_followup BOOL AS (state_json->'previousOutput'->>'followUp' IS NOT NULL) STORED, - timeout_date TIMESTAMPTZ AS (CASE - WHEN state_json->'wait'->>'type' = 'timeout' THEN (CEILING((state_json->>'waitStart')::INT/1000)::INT::TIMESTAMPTZ + (state_json->'wait'->>'value')::INTERVAL) - ELSE NULL - END) STORED, - fb_error_code varchar AS (state_json->'error'->>'code') STORED, - error_tag VARCHAR AS (state_json->'error'->>'tag') STORED, - next_retry TIMESTAMP AS ((FLOOR((POWER(2, JSON_ARRAY_LENGTH(state_json->'retries'))*60000 + (state_json->'retries'->>-1)::INT)::INT)/1000)::INT::TIMESTAMP) STORED, - CONSTRAINT "valid_state_json" CHECK (state_json ? 'state'), - PRIMARY KEY (userid, pageid) - );` - - insertQuery = `INSERT INTO - states(userid, pageid, updated, current_state, state_json) - VALUES ($1, $2, $3, $4, $5)` + pageInsertSql = ` + INSERT INTO credentials(entity, key, userid, details) + VALUES ('facebook_page', ($1)->>'id', '00000000-0000-0000-0000-000000000000', $1)` + surveyInsertSql = ` + INSERT INTO surveys(userid, shortcode, created, messages, formid, form, title) + VALUES ('00000000-0000-0000-0000-000000000000', $1, $2, $3, 'test-id', '{}', 'test-title');` + insertQuery = ` + INSERT INTO states(userid, pageid, updated, current_state, state_json) + VALUES ($1, $2, $3, $4, $5)` + insertUserSql = ` + INSERT INTO users(id, email) + VALUES ('00000000-0000-0000-0000-000000000000', 'test@test.com'); + ` ) +func before() { + _, err := http.Get("http://system/resetdb") + if err != nil { + panic(err) + } +} + func getEvents(ch <-chan *ExternalEvent) []*ExternalEvent { events := []*ExternalEvent{} for e := range ch { @@ -83,20 +54,25 @@ func makeStateJson(startTime time.Time, form, previousOutput string) string { } func TestGetRespondingsGetsOnlyThoseInGivenInterval(t *testing.T) { - pool := testPool() + before() + + dbCfg := getConfig() + pool := getConn(dbCfg) defer pool.Close() - mustExec(t, pool, stateSql) + mustExec(t, pool, insertUserSql) + mustExec(t, pool, pageInsertSql, `{"id": "11111111-1111-1111-1111-111111111111"}`) + mustExec(t, pool, insertQuery, "foo", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().Add(-2*time.Hour), "RESPONDING", `{"state": "RESPONDING"}`) mustExec(t, pool, insertQuery, "baz", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().Add(-6*time.Hour), "RESPONDING", `{"state": "RESPONDING"}`) @@ -107,25 +83,28 @@ func TestGetRespondingsGetsOnlyThoseInGivenInterval(t *testing.T) { assert.Equal(t, 1, len(events)) assert.Equal(t, "foo", events[0].User) - - mustExec(t, pool, "drop table states") } func TestGetRespondingsOnlyGetsThoseOutsideOfGracePeriod(t *testing.T) { - pool := testPool() + before() + + dbCfg := getConfig() + pool := getConn(dbCfg) defer pool.Close() - mustExec(t, pool, stateSql) + mustExec(t, pool, insertUserSql) + mustExec(t, pool, pageInsertSql, `{"id": "11111111-1111-1111-1111-111111111111"}`) + mustExec(t, pool, insertQuery, "foo", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().Add(-30*time.Minute), "RESPONDING", `{"state": "RESPONDING"}`) mustExec(t, pool, insertQuery, "baz", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().Add(-90*time.Minute), "RESPONDING", `{"state": "RESPONDING"}`) @@ -136,30 +115,33 @@ func TestGetRespondingsOnlyGetsThoseOutsideOfGracePeriod(t *testing.T) { assert.Equal(t, 1, len(events)) assert.Equal(t, "baz", events[0].User) - - mustExec(t, pool, "drop table states") } func TestGetBlockedOnlyGetsThoseWithCodesInsideWindow(t *testing.T) { - pool := testPool() + before() + + dbCfg := getConfig() + pool := getConn(dbCfg) defer pool.Close() - mustExec(t, pool, stateSql) + mustExec(t, pool, insertUserSql) + mustExec(t, pool, pageInsertSql, `{"id": "11111111-1111-1111-1111-111111111111"}`) + mustExec(t, pool, insertQuery, "foo", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().Add(-30*time.Minute), "BLOCKED", `{"state": "BLOCKED", "error": {"code": 2020}}`) mustExec(t, pool, insertQuery, "baz", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().Add(-30*time.Minute), "BLOCKED", `{"state": "BLOCKED", "error": {"code": 9999}}`) mustExec(t, pool, insertQuery, "qux", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().Add(-90*time.Minute), "BLOCKED", `{"state": "BLOCKED", "error": {"code": 2020}}`) @@ -170,31 +152,34 @@ func TestGetBlockedOnlyGetsThoseWithCodesInsideWindow(t *testing.T) { assert.Equal(t, 1, len(events)) assert.Equal(t, "foo", events[0].User) - - mustExec(t, pool, "drop table states") } func TestGetBlockedOnlyGetsThoseWithNextRetryPassed(t *testing.T) { - pool := testPool() + before() + + dbCfg := getConfig() + pool := getConn(dbCfg) defer pool.Close() - mustExec(t, pool, stateSql) + mustExec(t, pool, insertUserSql) + mustExec(t, pool, pageInsertSql, `{"id": "11111111-1111-1111-1111-111111111111"}`) + mustExec(t, pool, insertQuery, "foo", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().Add(-30*time.Minute), "BLOCKED", fmt.Sprintf(`{"state": "BLOCKED", "error": {"code": 2020}, "retries": [%d]}`, makeMs(-2*time.Minute))) mustExec(t, pool, insertQuery, "bar", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().Add(-30*time.Minute), "BLOCKED", fmt.Sprintf(`{"state": "BLOCKED", "error": {"code": 2020}, "retries": [%d]}`, makeMs(-1*time.Minute))) mustExec(t, pool, insertQuery, "baz", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().Add(-30*time.Minute), "BLOCKED", fmt.Sprintf(`{"state": "BLOCKED", "error": {"code": 2020}, "retries": [%d, %d, %d]}`, @@ -208,24 +193,27 @@ func TestGetBlockedOnlyGetsThoseWithNextRetryPassed(t *testing.T) { assert.Equal(t, 1, len(events)) assert.Equal(t, "foo", events[0].User) - - mustExec(t, pool, "drop table states") } func TestGetErroredGetsByTag(t *testing.T) { - pool := testPool() + before() + + dbCfg := getConfig() + pool := getConn(dbCfg) defer pool.Close() - mustExec(t, pool, stateSql) + mustExec(t, pool, insertUserSql) + mustExec(t, pool, pageInsertSql, `{"id": "11111111-1111-1111-1111-111111111111"}`) + mustExec(t, pool, insertQuery, "foo", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().Add(-30*time.Minute), "ERROR", `{"state": "ERROR", "error": {"tag": "NETWORK"}}`) mustExec(t, pool, insertQuery, "baz", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().Add(-30*time.Minute), "ERROR", `{"state": "ERROR", "error": {"tag": "NOTNET"}}`) @@ -236,35 +224,53 @@ func TestGetErroredGetsByTag(t *testing.T) { assert.Equal(t, 1, len(events)) assert.Equal(t, "foo", events[0].User) - - mustExec(t, pool, "drop table states") } func TestGetTimeoutsGetsOnlyExpiredTimeouts(t *testing.T) { - pool := testPool() + before() + + dbCfg := getConfig() + pool := getConn(dbCfg) defer pool.Close() + mustExec(t, pool, insertUserSql) + mustExec(t, pool, pageInsertSql, `{"id": "11111111-1111-1111-1111-111111111111"}`) + ts := time.Now().UTC().Add(-30 * time.Minute) ms := ts.Unix() * 1000 - - mustExec(t, pool, stateSql) mustExec(t, pool, insertQuery, "foo", - "bar", + "11111111-1111-1111-1111-111111111111", ts, "WAIT_EXTERNAL_EVENT", - fmt.Sprintf(`{"state": "WAIT_EXTERNAL_EVENT", - "waitStart": %v, - "wait": { "type": "timeout", "value": "20 minutes"}}`, ms)) + fmt.Sprintf(` + { + "state": "WAIT_EXTERNAL_EVENT", + "waitStart": %v, + "wait": { + "type": "timeout", + "value": "20 minutes" + } + } + `, ms), + ) mustExec(t, pool, insertQuery, "baz", - "bar", + "11111111-1111-1111-1111-111111111111", ts, "WAIT_EXTERNAL_EVENT", - fmt.Sprintf(`{"state": "WAIT_EXTERNAL_EVENT", - "waitStart": %v, - "wait": { "type": "timeout", "value": "40 minutes"}}`, ms)) + fmt.Sprintf(` + { + "state": "WAIT_EXTERNAL_EVENT", + "waitStart": %v, + "wait": { + "type": "timeout", + "value": "40 minutes" + } + } + `, ms), + ) cfg := &Config{} ch := Timeouts(cfg, pool) @@ -277,20 +283,19 @@ func TestGetTimeoutsGetsOnlyExpiredTimeouts(t *testing.T) { ev, _ := json.Marshal(events[0].Event) assert.Equal(t, string(ev), fmt.Sprintf(`{"type":"timeout","value":%v}`, ms)) - - mustExec(t, pool, "drop table states") } func TestFollowUpsGetsOnlyThoseBetweenMinAndMaxAndIgnoresAllSortsOfThings(t *testing.T) { - pool := testPool() - defer pool.Close() + before() - mustExec(t, pool, stateSql) - mustExec(t, pool, surveySql) + dbCfg := getConfig() + pool := getConn(dbCfg) + defer pool.Close() - mustExec(t, pool, pageInsertSql, `{"id": "bar"}`) - mustExec(t, pool, pageInsertSql, `{"id": "qux"}`) - mustExec(t, pool, pageInsertSql, `{"id": "quux"}`) + mustExec(t, pool, insertUserSql) + mustExec(t, pool, pageInsertSql, `{"id": "11111111-1111-1111-1111-111111111111"}`) + mustExec(t, pool, pageInsertSql, `{"id": "22222222-2222-2222-2222-222222222222"}`) + mustExec(t, pool, pageInsertSql, `{"id": "33333333-3333-3333-3333-333333333333"}`) mustExec(t, pool, surveyInsertSql, "with_followup", time.Now().UTC().Add(-50*time.Hour), `{"label.buttonHint.default": "this is follow up"}`) mustExec(t, pool, surveyInsertSql, "with_followup", time.Now().UTC().Add(-40*time.Hour), `{"label.buttonHint.default": "this is follow up"}`) mustExec(t, pool, surveyInsertSql, "with_followup", time.Now().UTC().Add(-20*time.Hour), `{"label.other": "not a follow up"}`) @@ -298,42 +303,42 @@ func TestFollowUpsGetsOnlyThoseBetweenMinAndMaxAndIgnoresAllSortsOfThings(t *tes mustExec(t, pool, insertQuery, "foo", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().UTC().Add(-30*time.Minute), "QOUT", makeStateJson(time.Now().UTC().Add(-30*time.Hour), "with_followup", `{"followUp": null}`)) mustExec(t, pool, insertQuery, "quux", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().UTC().Add(-30*time.Minute), "QOUT", makeStateJson(time.Now().UTC().Add(-10*time.Hour), "with_followup", `{"followUp": null}`)) mustExec(t, pool, insertQuery, "baz", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().UTC().Add(-30*time.Minute), "QOUT", makeStateJson(time.Now().UTC().Add(-60*time.Hour), "without_followup", `{"followUp": null}`)) mustExec(t, pool, insertQuery, "bar", - "qux", + "22222222-2222-2222-2222-222222222222", time.Now().UTC().Add(-30*time.Minute), "QOUT", makeStateJson(time.Now().UTC().Add(-60*time.Hour), "with_followup", `{"followUp": true}`)) mustExec(t, pool, insertQuery, "bar", - "quux", + "33333333-3333-3333-3333-333333333333", time.Now().UTC().Add(-30*time.Minute), "QOUT", makeStateJson(time.Now().UTC().Add(-60*time.Hour), "with_followup", `{"token": "token"}`)) mustExec(t, pool, insertQuery, "qux", - "bar", + "11111111-1111-1111-1111-111111111111", time.Now().UTC().Add(-90*time.Minute), "QOUT", makeStateJson(time.Now().UTC().Add(-60*time.Hour), "with_followup", `{}`)) @@ -348,6 +353,4 @@ func TestFollowUpsGetsOnlyThoseBetweenMinAndMaxAndIgnoresAllSortsOfThings(t *tes ev, _ := json.Marshal(events[0].Event) assert.Equal(t, string(ev), `{"type":"follow_up","value":"foo"}`) - - mustExec(t, pool, "drop table states") } diff --git a/dean/test.yaml b/dean/test.yaml new file mode 100644 index 00000000..5879032d --- /dev/null +++ b/dean/test.yaml @@ -0,0 +1,94 @@ +version: '3' + +services: + main: + depends_on: + - system + image: ${APP_NAME}_dev + build: + context: . + dockerfile: Dockerfile.dev + environment: + CHATBASE_DATABASE: chatroach + CHATBASE_HOST: cockroachdb + CHATBASE_PORT: 26257 + CHATBASE_USER: root + BOTSERVER_URL: "" + DEAN_FB_CODES: "" + DEAN_ERROR_TAGS: "" + DEAN_ERROR_INTERVAL: "" + DEAN_BLOCKED_INTERVAL: "" + DEAN_RESPONDING_INTERVAL: "" + DEAN_RESPONDING_GRACE: "" + DEAN_QUERIES: "" + DEAN_SEND_DELAY: "" + DEAN_FOLLOWUP_MIN: "" + DEAN_FOLLOWUP_MAX: "" + command: | + sh -c ' + echo "Running tests..." + go mod tidy + + if [ -z "${ARG}" ] + then + nodemon \ + --ext "*" \ + --exec "go test -cover" + fi + + if [ "${ARG}" = "--is-ci" ] + then + go test -cover + exit + fi + + nodemon \ + --ext "*" \ + --exec "go test -cover -run ${ARG}" + ' + volumes: + - ./:/app + networks: + - fly + system: + build: + context: ../system + environment: + CHATBASE_DATABASE: chatroach + CHATBASE_HOST: cockroachdb + CHATBASE_PORT: 26257 + CHATBASE_USER: root + PORT: 80 + command: go run . + ports: + - 80:80 + volumes: + - ../system:/app + networks: + - fly + initdb: + image: cockroachdb/cockroach:v20.1.4 + depends_on: + - cockroachdb + entrypoint: | + sh -c ' + /tools/wait-for-it.sh cockroachdb:26257 -t 60 + cat /migrations/* > /tmp/merged-latest.sql + cat /tmp/merged-latest.sql | ./cockroach sql --insecure --host cockroachdb + ' + volumes: + - ../devops:/tools + - ../devops/sql:/migrations + networks: + - fly + cockroachdb: + image: cockroachdb/cockroach:v20.1.4 + command: start --insecure + ports: + - 26257:26257 + networks: + - fly + +networks: + fly: + driver: bridge diff --git a/dean/test_helpers.go b/dean/test_helpers.go index 98ba75e6..d0a95ac1 100644 --- a/dean/test_helpers.go +++ b/dean/test_helpers.go @@ -2,28 +2,12 @@ package main import ( "context" - "fmt" "testing" "github.com/jackc/pgconn" "github.com/jackc/pgx/v4/pgxpool" ) -func getCol(pool *pgxpool.Pool, table string, col string) []string { - rows, err := pool.Query(context.Background(), fmt.Sprintf("select %v from %v", col, table)) - if err != nil { - panic(err) - } - - res := []string{} - for rows.Next() { - var col string - _ = rows.Scan(&col) - res = append(res, col) - } - return res -} - func mustExec(t testing.TB, conn *pgxpool.Pool, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag) { var err error if commandTag, err = conn.Exec(context.Background(), sql, arguments...); err != nil { @@ -31,14 +15,3 @@ func mustExec(t testing.TB, conn *pgxpool.Pool, sql string, arguments ...interfa } return } - -func testPool() *pgxpool.Pool { - config, err := pgxpool.ParseConfig("postgres://root@localhost:5433/test") - handle(err) - - ctx := context.Background() - pool, err := pgxpool.ConnectConfig(ctx, config) - handle(err) - - return pool -} diff --git a/devops/sql/migrate-21.sql b/devops/sql/migrate-21.sql new file mode 100644 index 00000000..fed31f41 --- /dev/null +++ b/devops/sql/migrate-21.sql @@ -0,0 +1,2 @@ +ALTER TABLE chatroach.states ADD CONSTRAINT valid_state_json CHECK (state_json ? 'state'); +ALTER TABLE chatroach.states ADD CONSTRAINT fk_facebook_page_id FOREIGN KEY (pageid) REFERENCES chatroach.credentials(facebook_page_id) ON DELETE CASCADE; diff --git a/dinersclub/Dockerfile.dev b/dinersclub/Dockerfile.dev index faf295c1..db6e12c2 100644 --- a/dinersclub/Dockerfile.dev +++ b/dinersclub/Dockerfile.dev @@ -3,12 +3,12 @@ FROM golang:alpine RUN apk add --no-cache \ gcc \ libc-dev \ - librdkafka-dev=1.8.2-r0 --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community \ - readline-dev + librdkafka-dev=1.8.2-r0 \ + npm RUN mkdir /app COPY go.mod /app WORKDIR /app RUN go mod download -RUN go get -u github.com/nathany/looper +RUN npm install -g nodemon diff --git a/dinersclub/go.mod b/dinersclub/go.mod index 79b78ce5..a80e60d7 100644 --- a/dinersclub/go.mod +++ b/dinersclub/go.mod @@ -3,20 +3,16 @@ module github.com/vlab-research/dinersclub go 1.15 require ( - github.com/caarlos0/env/v6 v6.3.0 + github.com/caarlos0/env/v6 v6.9.1 github.com/cenkalti/backoff v2.2.1+incompatible - github.com/confluentinc/confluent-kafka-go v1.7.0 + github.com/confluentinc/confluent-kafka-go v1.8.2 github.com/dgraph-io/ristretto v0.1.0 - github.com/go-playground/validator/v10 v10.4.1 - github.com/jackc/pgconn v1.7.2 - github.com/jackc/pgx/v4 v4.9.2 - github.com/leodido/go-urn v1.2.1 // indirect + github.com/go-playground/validator/v10 v10.10.0 + github.com/jackc/pgconn v1.10.1 + github.com/jackc/pgx/v4 v4.14.1 github.com/nandanrao/chance v0.0.2 - github.com/stretchr/testify v1.6.1 - github.com/vlab-research/botparty v0.0.0-20200917171250-abbbd36eb095 + github.com/stretchr/testify v1.7.0 + github.com/vlab-research/botparty v0.0.1 github.com/vlab-research/go-reloadly v0.0.13 - github.com/vlab-research/spine v0.0.4 - golang.org/x/crypto v0.0.0-20201217014255-9d1352758620 // indirect - golang.org/x/sys v0.0.0-20201218084310-7d0127a74742 // indirect - golang.org/x/text v0.3.4 // indirect + github.com/vlab-research/spine v0.0.5 ) diff --git a/dinersclub/go.sum b/dinersclub/go.sum index 77aafe11..a284c4f2 100644 --- a/dinersclub/go.sum +++ b/dinersclub/go.sum @@ -1,13 +1,15 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/caarlos0/env/v6 v6.3.0 h1:PaqGnS5iHScZ5SnZNBPvQbA2VE/eMAwlp51mKGuEZLg= -github.com/caarlos0/env/v6 v6.3.0/go.mod h1:nXKfztzgWXH0C5Adnp+gb+vXHmMjKdBnMrSVSczSkiw= +github.com/caarlos0/env/v6 v6.9.1 h1:zOkkjM0F6ltnQ5eBX6IPI41UP/KDGEK7rRPwGCNos8k= +github.com/caarlos0/env/v6 v6.9.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= @@ -18,8 +20,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/confluentinc/confluent-kafka-go v1.5.2/go.mod h1:u2zNLny2xq+5rWeTQjFHbDzzNuba4P1vo31r9r4uAdg= -github.com/confluentinc/confluent-kafka-go v1.7.0 h1:tXh3LWb2Ne0WiU3ng4h5qiGA9XV61rz46w60O+cq8bM= -github.com/confluentinc/confluent-kafka-go v1.7.0/go.mod h1:u2zNLny2xq+5rWeTQjFHbDzzNuba4P1vo31r9r4uAdg= +github.com/confluentinc/confluent-kafka-go v1.8.2 h1:PBdbvYpyOdFLehj8j+9ba7FL4c4Moxn79gy9cYKxG5E= +github.com/confluentinc/confluent-kafka-go v1.8.2/go.mod h1:u2zNLny2xq+5rWeTQjFHbDzzNuba4P1vo31r9r4uAdg= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -28,6 +30,7 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -44,20 +47,24 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.3.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= -github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0= +github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= @@ -85,15 +92,17 @@ github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgO github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= -github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.7.2 h1:195tt17jkjy+FrFlY0pgyrul5kRLb7BGXY3JTrNxeXU= -github.com/jackc/pgconn v1.7.2/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.10.1 h1:DzdIHIjG1AxGwoEEqS+mGsURyjt4enSmqzACXvVzOT8= +github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= @@ -102,34 +111,29 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.0.6 h1:b1105ZGEMFe7aCvrT1Cca3VoVb4ZFMaFJLJcg/3zD+8= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5ns= +github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= -github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= -github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= -github.com/jackc/pgtype v1.6.1 h1:CAtFD7TS95KrxRAh3bidgLwva48WYxk8YkbHZsSWfbI= -github.com/jackc/pgtype v1.6.1/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.9.1 h1:MJc2s0MFS8C3ok1wQTdQxWuXQcB6+HwAm5x1CzW7mf0= +github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= -github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= -github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= -github.com/jackc/pgx/v4 v4.9.2 h1:1V7EAc5jvIqXwdzgk8+YyOK+4071hhePzBCAF6gxUUw= -github.com/jackc/pgx/v4 v4.9.2/go.mod h1:Jt/xJDqjUDUOMSv8VMWPQlCObVgF2XOgqKsW8S4ROYA= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.14.1 h1:71oo1KAGI6mXhLiTMn6iDFcp3e7+zon/capWjl2OEFU= +github.com/jackc/pgx/v4 v4.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.2 h1:mpQEXihFnWGDy6X98EOTh81JYuxn7txby8ilJ3iIPGM= -github.com/jackc/puddle v1.1.2/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.2.0 h1:DNDKdn/pDrWvDWyT2FYvpZVE81OAhWrjCv19I9n108Q= +github.com/jackc/puddle v1.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jszwec/csvutil v1.4.0/go.mod h1:Rpu7Uu9giO9subDyMCIQfHVDuLrcaC36UA4YcJjGBkg= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= @@ -138,28 +142,28 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -169,6 +173,7 @@ github.com/nandanrao/chance v0.0.2 h1:PsFvVj1sZ9O1mKA6N3ep+t4M7e5XgHGFKt3ta646EL github.com/nandanrao/chance v0.0.2/go.mod h1:hQBs2tnQgBpcZbCKBPVZehs9lxpgCtsdsSBLQa7CJEE= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -186,14 +191,17 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -214,44 +222,50 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/vlab-research/botparty v0.0.0-20200917171250-abbbd36eb095 h1:vi5UbYAlmOe/d0Jg3RVsYQihgEQEWsXBlWMaSk+izEM= -github.com/vlab-research/botparty v0.0.0-20200917171250-abbbd36eb095/go.mod h1:UtpX/9Pm3GBQ8cJOTkdZaQGfqjDGGpqiJD3YkxzLP0U= +github.com/vlab-research/botparty v0.0.1 h1:sA0uKB30LmaGIQ42l/Jg7hHq0noHyxnuIpmLQS3IhYo= +github.com/vlab-research/botparty v0.0.1/go.mod h1:UtpX/9Pm3GBQ8cJOTkdZaQGfqjDGGpqiJD3YkxzLP0U= github.com/vlab-research/go-reloadly v0.0.13 h1:nFxYMJ/jS+6hkQSoL4K3fx9wqymXMJHoZZ3cDlD/rUc= github.com/vlab-research/go-reloadly v0.0.13/go.mod h1:bJHsKM3lTjw1tahB6mK0JXJgYtC0zrUmJ7LS1GSaepA= github.com/vlab-research/gotils v0.0.2 h1:o/LceCxyu7x9xogMDBBc37xAOhzGZoSxyDYkatq8NR0= github.com/vlab-research/gotils v0.0.2/go.mod h1:ACGZhkXG9rnKZqUiMgIvR7EeENyoTIZuriv5DXYUH2I= -github.com/vlab-research/spine v0.0.4 h1:sJfRCMUumRM7HoQKBTlgV6Cna2QpNV/SEH9zc3ujMZA= -github.com/vlab-research/spine v0.0.4/go.mod h1:pYZvCHWpWnwPnTvHevLuHNSnggmUzU2fFirF+V6M5zM= +github.com/vlab-research/spine v0.0.5 h1:cvP/Ib4fssdgHPh9qzQd0xTD8eUdcsFq/viL/k2FH2M= +github.com/vlab-research/spine v0.0.5/go.mod h1:pYZvCHWpWnwPnTvHevLuHNSnggmUzU2fFirF+V6M5zM= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201217014255-9d1352758620 h1:3wPMTskHO3+O6jqTEXyFcsnuxMQOqYSaHsDxcbUXpqA= -golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -260,6 +274,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -275,19 +290,22 @@ golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201218084310-7d0127a74742 h1:+CBz4km/0KPU3RGTwARGh/noP3bEwtHcq+0YcBQM2JQ= -golang.org/x/sys v0.0.0-20201218084310-7d0127a74742/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -298,26 +316,29 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/dinersclub/test.yaml b/dinersclub/test.yaml index 2b246c54..5c5a9f71 100644 --- a/dinersclub/test.yaml +++ b/dinersclub/test.yaml @@ -34,12 +34,23 @@ services: sh -c ' echo "Running tests..." go mod tidy - if [ "${IS_CI}" = "" ] + + if [ -z "${ARG}" ] then - go test -tags dynamic || true - looper -tags dynamic + nodemon \ + --ext "*" \ + --exec "go test -cover -tags dynamic" fi - go test -tags dynamic + + if [ "${ARG}" = "--is-ci" ] + then + go test -cover -tags dynamic + exit + fi + + nodemon \ + --ext "*" \ + --exec "go test -cover -tags dynamic -run ${ARG}" ' volumes: - ./:/app diff --git a/formcentral/Dockerfile.dev b/formcentral/Dockerfile.dev index ab411bf9..7836ed31 100644 --- a/formcentral/Dockerfile.dev +++ b/formcentral/Dockerfile.dev @@ -3,11 +3,11 @@ FROM golang:alpine RUN apk add --no-cache \ gcc \ libc-dev \ - readline-dev + npm RUN mkdir /app COPY go.mod /app WORKDIR /app RUN go mod download -RUN go get -u github.com/nathany/looper +RUN npm install -g nodemon diff --git a/formcentral/go.mod b/formcentral/go.mod index 451a2b70..cfc05c82 100644 --- a/formcentral/go.mod +++ b/formcentral/go.mod @@ -3,10 +3,10 @@ module github.com/vlab-research/formcentral go 1.15 require ( - github.com/caarlos0/env/v6 v6.4.0 - github.com/jackc/pgconn v1.7.2 - github.com/jackc/pgx/v4 v4.9.2 - github.com/labstack/echo/v4 v4.1.17 - github.com/stretchr/testify v1.6.1 - github.com/vlab-research/trans v0.0.6 + github.com/caarlos0/env/v6 v6.9.1 + github.com/jackc/pgconn v1.10.1 + github.com/jackc/pgx/v4 v4.14.1 + github.com/labstack/echo/v4 v4.6.1 + github.com/stretchr/testify v1.7.0 + github.com/vlab-research/trans v0.0.8 ) diff --git a/formcentral/go.sum b/formcentral/go.sum index 1d812f29..df501630 100644 --- a/formcentral/go.sum +++ b/formcentral/go.sum @@ -1,7 +1,9 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/caarlos0/env v3.5.0+incompatible h1:Yy0UN8o9Wtr/jGHZDpCBLpNrzcFLLM2yixi/rBrKyJs= -github.com/caarlos0/env/v6 v6.4.0 h1:fUo2hQNR3O7Yb7E2sYy8cxY42BRvFxWa0G4XBMLJAQM= -github.com/caarlos0/env/v6 v6.4.0/go.mod h1:MX/8qQ2zCofGGkb7FxjmDLOOjUylO2b7dbsIpN30bnY= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/caarlos0/env/v6 v6.9.1 h1:zOkkjM0F6ltnQ5eBX6IPI41UP/KDGEK7rRPwGCNos8k= +github.com/caarlos0/env/v6 v6.9.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc= +github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= @@ -9,9 +11,12 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= @@ -21,14 +26,17 @@ github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgO github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= -github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.7.2 h1:195tt17jkjy+FrFlY0pgyrul5kRLb7BGXY3JTrNxeXU= -github.com/jackc/pgconn v1.7.2/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.10.1 h1:DzdIHIjG1AxGwoEEqS+mGsURyjt4enSmqzACXvVzOT8= +github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= @@ -37,63 +45,60 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.0.6 h1:b1105ZGEMFe7aCvrT1Cca3VoVb4ZFMaFJLJcg/3zD+8= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5ns= +github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= -github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= -github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= -github.com/jackc/pgtype v1.6.1 h1:CAtFD7TS95KrxRAh3bidgLwva48WYxk8YkbHZsSWfbI= -github.com/jackc/pgtype v1.6.1/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig= -github.com/jackc/pgx v3.6.2+incompatible h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.9.1 h1:MJc2s0MFS8C3ok1wQTdQxWuXQcB6+HwAm5x1CzW7mf0= +github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= -github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= -github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= -github.com/jackc/pgx/v4 v4.9.2 h1:1V7EAc5jvIqXwdzgk8+YyOK+4071hhePzBCAF6gxUUw= -github.com/jackc/pgx/v4 v4.9.2/go.mod h1:Jt/xJDqjUDUOMSv8VMWPQlCObVgF2XOgqKsW8S4ROYA= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.14.1 h1:71oo1KAGI6mXhLiTMn6iDFcp3e7+zon/capWjl2OEFU= +github.com/jackc/pgx/v4 v4.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.2 h1:mpQEXihFnWGDy6X98EOTh81JYuxn7txby8ilJ3iIPGM= -github.com/jackc/puddle v1.1.2/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.2.0 h1:DNDKdn/pDrWvDWyT2FYvpZVE81OAhWrjCv19I9n108Q= +github.com/jackc/puddle v1.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/labstack/echo v1.4.4 h1:1bEiBNeGSUKxcPDGfZ/7IgdhJJZx8wV/pICJh4W2NJI= -github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg= -github.com/labstack/echo/v4 v4.1.17 h1:PQIBaRplyRy3OjwILGkPg89JRtH2x5bssi59G2EL3fo= -github.com/labstack/echo/v4 v4.1.17/go.mod h1:Tn2yRQL/UclUalpb5rPdXDevbkJ+lp/2svdyFBg6CHQ= +github.com/labstack/echo/v4 v4.6.1 h1:OMVsrnNFzYlGSdaiYGHbgWQnr+JM7NG+B9suCPie14M= +github.com/labstack/echo/v4 v4.6.1/go.mod h1:RnjgMWNDB9g/HucVWhQYNQP9PvbYf6adqftqryo7s9k= github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -103,7 +108,8 @@ github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OK github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -113,46 +119,49 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/vlab-research/trans v0.0.2 h1:w9ft2X2V0diTXqQyD1TKRspkAtyGGMDsZNieEcbqPoI= -github.com/vlab-research/trans v0.0.2/go.mod h1:760R69NitmG7XcxEOF0OuuQjxvZiLGqG5sL493lmfjw= -github.com/vlab-research/trans v0.0.5 h1:hXsALcO5vOvRSNrboYaWbOVnF65YqLRxSPtMlLpeRDA= -github.com/vlab-research/trans v0.0.5/go.mod h1:760R69NitmG7XcxEOF0OuuQjxvZiLGqG5sL493lmfjw= -github.com/vlab-research/trans v0.0.6 h1:ZZCWXru4xYwe8PZnLgp0KWB8nOGFZVJ8Yy4qTBQ4vio= -github.com/vlab-research/trans v0.0.6/go.mod h1:760R69NitmG7XcxEOF0OuuQjxvZiLGqG5sL493lmfjw= +github.com/vlab-research/trans v0.0.8 h1:897LEi/sex1wRNhG2G8DKmzmLNuKB5torJNTiR7GNVI= +github.com/vlab-research/trans v0.0.8/go.mod h1:760R69NitmG7XcxEOF0OuuQjxvZiLGqG5sL493lmfjw= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210913180222-943fd674d43e h1:+b/22bPvDYt4NPDcy4xAGCmON713ONAWFeY3Z7I3tR8= +golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -161,16 +170,25 @@ golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6 h1:DvY3Zkh7KabQE/kfzMvYvKirSiguP9Q/veMtkYyf0o8= -golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 h1:xrCZDmdtoloIiooiA9q0OQb9r8HejIHYoHGhGCe1pGg= +golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -178,12 +196,14 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= diff --git a/formcentral/server_test.go b/formcentral/server_test.go index db97e1d1..ada4d47c 100644 --- a/formcentral/server_test.go +++ b/formcentral/server_test.go @@ -18,9 +18,9 @@ import ( ) const ( - surveyid = "00000000-0000-0000-0000-000000000000" - userid = "55555555-5555-5555-5555-555555555555" - insertUser = `INSERT INTO users(id, email) VALUES ($1, 'test@test.com');` + surveyid = "00000000-0000-0000-0000-000000000000" + userid = "55555555-5555-5555-5555-555555555555" + insertUser = `INSERT INTO users(id, email) VALUES ($1, 'test@test.com');` insertSurvey = ` INSERT INTO surveys(id, userid, form, formid, shortcode, title, created) VALUES ($1, $2, $3, 'test-form-id', 'test-sc', 'test-title', NOW()); diff --git a/formcentral/test.yaml b/formcentral/test.yaml index d3d7c052..ba217c4d 100644 --- a/formcentral/test.yaml +++ b/formcentral/test.yaml @@ -19,12 +19,23 @@ services: sh -c ' echo "Running tests..." go mod tidy - if [ "${IS_CI}" = "" ] + + if [ -z "${ARG}" ] then - go test || true - looper + nodemon \ + --ext "*" \ + --exec "go test -cover" fi - go test + + if [ "${ARG}" = "--is-ci" ] + then + go test -cover + exit + fi + + nodemon \ + --ext "*" \ + --exec "go test -cover -run ${ARG}" ' volumes: - ./:/app diff --git a/linksniffer/.dockerignore b/linksniffer/.dockerignore deleted file mode 100644 index 73666cf3..00000000 --- a/linksniffer/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -linksniffer -.env diff --git a/linksniffer/.gitignore b/linksniffer/.gitignore deleted file mode 100644 index d47d5cfc..00000000 --- a/linksniffer/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.env -linksniffer diff --git a/linksniffer/Dockerfile.dev b/linksniffer/Dockerfile.dev new file mode 100644 index 00000000..7836ed31 --- /dev/null +++ b/linksniffer/Dockerfile.dev @@ -0,0 +1,13 @@ +FROM golang:alpine + +RUN apk add --no-cache \ + gcc \ + libc-dev \ + npm + +RUN mkdir /app +COPY go.mod /app +WORKDIR /app + +RUN go mod download +RUN npm install -g nodemon diff --git a/linksniffer/go.mod b/linksniffer/go.mod index faf1b214..8074d992 100644 --- a/linksniffer/go.mod +++ b/linksniffer/go.mod @@ -3,7 +3,6 @@ module github.com/vlab-research/linksniffer go 1.13 require ( - github.com/labstack/echo/v4 v4.1.14 - github.com/stretchr/testify v1.6.1 - github.com/vlab-research/botparty v0.0.0-20200917171250-abbbd36eb095 // indirect + github.com/labstack/echo/v4 v4.6.1 + github.com/stretchr/testify v1.7.0 ) diff --git a/linksniffer/go.sum b/linksniffer/go.sum index a417c195..6f093463 100644 --- a/linksniffer/go.sum +++ b/linksniffer/go.sum @@ -1,52 +1,53 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/labstack/echo/v4 v4.1.14 h1:h8XP66UfB3tUm+L3QPw7tmwAu3pJaA/nyfHPCcz46ic= -github.com/labstack/echo/v4 v4.1.14/go.mod h1:Q5KZ1vD3V5FEzjM79hjwVrC3ABr7F5IdM23bXQMRDGg= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/labstack/echo/v4 v4.6.1 h1:OMVsrnNFzYlGSdaiYGHbgWQnr+JM7NG+B9suCPie14M= +github.com/labstack/echo/v4 v4.6.1/go.mod h1:RnjgMWNDB9g/HucVWhQYNQP9PvbYf6adqftqryo7s9k= github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4= -github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/vlab-research/botparty v0.0.0-20200917171250-abbbd36eb095 h1:vi5UbYAlmOe/d0Jg3RVsYQihgEQEWsXBlWMaSk+izEM= -github.com/vlab-research/botparty v0.0.0-20200917171250-abbbd36eb095/go.mod h1:UtpX/9Pm3GBQ8cJOTkdZaQGfqjDGGpqiJD3YkxzLP0U= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 h1:sKJQZMuxjOAR/Uo2LBfU90onWEf1dF4C+0hPJCc9Mpc= -golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210913180222-943fd674d43e h1:+b/22bPvDYt4NPDcy4xAGCmON713ONAWFeY3Z7I3tR8= +golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8 h1:JA8d3MPx/IToSyXZG/RhwYEtfrKO1Fxrqe8KrkiLXKM= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 h1:xrCZDmdtoloIiooiA9q0OQb9r8HejIHYoHGhGCe1pGg= +golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/linksniffer/server_test.go b/linksniffer/server_test.go index de81d056..6b8f7ab8 100644 --- a/linksniffer/server_test.go +++ b/linksniffer/server_test.go @@ -9,18 +9,8 @@ import ( "github.com/labstack/echo/v4" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" ) -type MockEventer struct { - mock.Mock -} - -func (m *MockEventer) Send(id string, url string) error { - args := m.Called(id, url) - return args.Error(0) -} - func TestGetEvent_forwardHttps(t *testing.T) { e := echo.New() diff --git a/linksniffer/test.yaml b/linksniffer/test.yaml new file mode 100644 index 00000000..268a19f3 --- /dev/null +++ b/linksniffer/test.yaml @@ -0,0 +1,32 @@ +version: '3' + +services: + main: + image: ${APP_NAME}_dev + build: + context: . + dockerfile: Dockerfile.dev + command: | + sh -c ' + echo "Running tests..." + go mod tidy + + if [ -z "${ARG}" ] + then + nodemon \ + --ext "*" \ + --exec "go test -cover" + fi + + if [ "${ARG}" = "--is-ci" ] + then + go test -cover + exit + fi + + nodemon \ + --ext "*" \ + --exec "go test -cover -run ${ARG}" + ' + volumes: + - ./:/app diff --git a/replybot/Dockerfile b/replybot/Dockerfile index d736e8bd..0a7b5403 100644 --- a/replybot/Dockerfile +++ b/replybot/Dockerfile @@ -1,11 +1,12 @@ FROM node:10-stretch -WORKDIR /usr/src/app +RUN mkdir /app +WORKDIR /app RUN npm install node-rdkafka -COPY package.json /usr/src/app +COPY package.json /app RUN npm install -COPY . /usr/src/app +COPY . /app -CMD [ "npm", "start"] +CMD [ "npm", "start" ] diff --git a/replybot/package.json b/replybot/package.json index f0e50a93..2f960849 100644 --- a/replybot/package.json +++ b/replybot/package.json @@ -4,10 +4,12 @@ "description": "Using Typeform to create Facebook Bots", "main": "index.js", "scripts": { - "_test": "mocha -w --colors lib/**/*.test.js", "start": "node lib/index.js", "dev": "nodemon lib/index.js", + "_test": "mocha -w --colors lib/**/*.test.js", "test": "nyc npm run _test", + "_test-ci": "mocha --colors lib/**/*.test.js", + "test-ci": "nyc npm run _test-ci", "report": "nyc report", "lint": "eslint ." }, diff --git a/replybot/test.yaml b/replybot/test.yaml new file mode 100644 index 00000000..bc71847b --- /dev/null +++ b/replybot/test.yaml @@ -0,0 +1,19 @@ +version: '3' + +services: + main: + image: ${APP_NAME}_dev + build: . + command: | + sh -c ' + echo "Running tests..." + npm install + if [ "${ARG}" = "--is-ci" ] + then + npm run test-ci + exit + fi + npm test + ' + volumes: + - ./:/app diff --git a/scribble/.dockerignore b/scribble/.dockerignore deleted file mode 100644 index 5b9b3947..00000000 --- a/scribble/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -Dockerfile -values.yaml -chart/ \ No newline at end of file diff --git a/scribble/.gitignore b/scribble/.gitignore deleted file mode 100644 index e69de29b..00000000 diff --git a/scribble/Dockerfile.dev b/scribble/Dockerfile.dev new file mode 100644 index 00000000..db6e12c2 --- /dev/null +++ b/scribble/Dockerfile.dev @@ -0,0 +1,14 @@ +FROM golang:alpine + +RUN apk add --no-cache \ + gcc \ + libc-dev \ + librdkafka-dev=1.8.2-r0 \ + npm + +RUN mkdir /app +COPY go.mod /app +WORKDIR /app + +RUN go mod download +RUN npm install -g nodemon diff --git a/scribble/config.go b/scribble/config.go new file mode 100644 index 00000000..98f7b528 --- /dev/null +++ b/scribble/config.go @@ -0,0 +1,35 @@ +package main + +import ( + "time" + "log" + + "github.com/caarlos0/env/v6" +) + +type Config struct { + DbName string `env:"CHATBASE_DATABASE,required"` + DbUser string `env:"CHATBASE_USER,required"` + DbHost string `env:"CHATBASE_HOST,required"` + DbPort int `env:"CHATBASE_PORT,required"` + DbMaxConns int `env:"CHATBASE_MAX_CONNECTIONS,required"` + KafkaBrokers string `env:"KAFKA_BROKERS,required"` + KafkaPollTimeout time.Duration `env:"KAFKA_POLL_TIMEOUT,required"` + Topic string `env:"KAFKA_TOPIC,required"` + Group string `env:"KAFKA_GROUP,required"` + BatchSize int `env:"SCRIBBLE_BATCH_SIZE,required"` + ChunkSize int `env:"SCRIBBLE_CHUNK_SIZE,required"` + Destination string `env:"SCRIBBLE_DESTINATION,required"` + Handlers string `env:"SCRIBBLE_ERROR_HANDLERS,required"` +} + +func getConfig() *Config { + cfg := Config{} + err := env.Parse(&cfg) + handle(err) + if cfg.Handlers != "" && cfg.ChunkSize != 1 { + log.Fatalf("Scribble can only pass on errors with a chunk size of 1. Passed chunk size: %v", + cfg.ChunkSize) + } + return &cfg +} diff --git a/scribble/go.mod b/scribble/go.mod index 3e5e11a5..0a0ddea0 100644 --- a/scribble/go.mod +++ b/scribble/go.mod @@ -3,16 +3,13 @@ module github.com/vlab-research/scribble go 1.15 require ( - github.com/caarlos0/env/v6 v6.3.0 - github.com/confluentinc/confluent-kafka-go v1.7.0 - github.com/dgraph-io/ristretto v0.0.3 - github.com/go-playground/validator/v10 v10.3.0 - github.com/jackc/pgconn v1.6.4 - github.com/jackc/pgproto3/v2 v2.0.4 // indirect - github.com/jackc/pgx/v4 v4.8.1 - github.com/stretchr/testify v1.6.1 - github.com/vlab-research/spine v0.0.4 - github.com/vlab-research/trans v0.0.6 - golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + github.com/caarlos0/env/v6 v6.9.1 + github.com/confluentinc/confluent-kafka-go v1.8.2 + github.com/dgraph-io/ristretto v0.1.0 + github.com/go-playground/validator/v10 v10.10.0 + github.com/jackc/pgconn v1.10.1 + github.com/jackc/pgx/v4 v4.14.1 + github.com/stretchr/testify v1.7.0 + github.com/vlab-research/spine v0.0.5 + github.com/vlab-research/trans v0.0.8 ) diff --git a/scribble/go.sum b/scribble/go.sum index a19d72d3..97ec9dfd 100644 --- a/scribble/go.sum +++ b/scribble/go.sum @@ -1,37 +1,43 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/caarlos0/env/v6 v6.3.0 h1:PaqGnS5iHScZ5SnZNBPvQbA2VE/eMAwlp51mKGuEZLg= -github.com/caarlos0/env/v6 v6.3.0/go.mod h1:nXKfztzgWXH0C5Adnp+gb+vXHmMjKdBnMrSVSczSkiw= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/caarlos0/env/v6 v6.9.1 h1:zOkkjM0F6ltnQ5eBX6IPI41UP/KDGEK7rRPwGCNos8k= +github.com/caarlos0/env/v6 v6.9.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/confluentinc/confluent-kafka-go v1.4.2 h1:13EK9RTujF7lVkvHQ5Hbu6bM+Yfrq8L0MkJNnjHSd4Q= -github.com/confluentinc/confluent-kafka-go v1.4.2/go.mod h1:u2zNLny2xq+5rWeTQjFHbDzzNuba4P1vo31r9r4uAdg= -github.com/confluentinc/confluent-kafka-go v1.5.2 h1:l+qt+a0Okmq0Bdr1P55IX4fiwFJyg0lZQmfHkAFkv7E= github.com/confluentinc/confluent-kafka-go v1.5.2/go.mod h1:u2zNLny2xq+5rWeTQjFHbDzzNuba4P1vo31r9r4uAdg= -github.com/confluentinc/confluent-kafka-go v1.7.0 h1:tXh3LWb2Ne0WiU3ng4h5qiGA9XV61rz46w60O+cq8bM= -github.com/confluentinc/confluent-kafka-go v1.7.0/go.mod h1:u2zNLny2xq+5rWeTQjFHbDzzNuba4P1vo31r9r4uAdg= +github.com/confluentinc/confluent-kafka-go v1.8.2 h1:PBdbvYpyOdFLehj8j+9ba7FL4c4Moxn79gy9cYKxG5E= +github.com/confluentinc/confluent-kafka-go v1.8.2/go.mod h1:u2zNLny2xq+5rWeTQjFHbDzzNuba4P1vo31r9r4uAdg= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgraph-io/ristretto v0.0.3 h1:jh22xisGBjrEVnRZ1DVTpBVQm0Xndu8sMl0CWDzSIBI= -github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI= +github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.3.0 h1:nZU+7q+yJoFmwvNgv/LnPUkwPal62+b2xXj0AU1Es7o= -github.com/go-playground/validator/v10 v10.3.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0= +github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= @@ -41,15 +47,17 @@ github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgO github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= -github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.6.4 h1:S7T6cx5o2OqmxdHaXLH1ZeD1SbI8jBznyYE9Ec0RCQ8= -github.com/jackc/pgconn v1.6.4/go.mod h1:w2pne1C2tZgP+TvjqLpOigGzNqjBgQW9dUw/4Chex78= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.10.1 h1:DzdIHIjG1AxGwoEEqS+mGsURyjt4enSmqzACXvVzOT8= +github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= @@ -58,74 +66,72 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.0.2 h1:q1Hsy66zh4vuNsajBUF2PNqfAMMfxU5mk594lPE9vjY= -github.com/jackc/pgproto3/v2 v2.0.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.0.4 h1:RHkX5ZUD9bl/kn0f9dYUWs1N7Nwvo1wwUYvKiR26Zco= -github.com/jackc/pgproto3/v2 v2.0.4/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5ns= +github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= -github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= -github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= -github.com/jackc/pgtype v1.4.2 h1:t+6LWm5eWPLX1H5Se702JSBcirq6uWa4jiG4wV1rAWY= -github.com/jackc/pgtype v1.4.2/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.9.1 h1:MJc2s0MFS8C3ok1wQTdQxWuXQcB6+HwAm5x1CzW7mf0= +github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= -github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= -github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= -github.com/jackc/pgx/v4 v4.8.1 h1:SUbCLP2pXvf/Sr/25KsuI4aTxiFYIvpfk4l6aTSdyCw= -github.com/jackc/pgx/v4 v4.8.1/go.mod h1:4HOLxrl8wToZJReD04/yB20GDwf4KBYETvlHciCnwW0= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.14.1 h1:71oo1KAGI6mXhLiTMn6iDFcp3e7+zon/capWjl2OEFU= +github.com/jackc/pgx/v4 v4.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.1 h1:PJAw7H/9hoWC4Kf3J8iNmL1SwA6E8vfsLqBiL+F6CtI= -github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.2.0 h1:DNDKdn/pDrWvDWyT2FYvpZVE81OAhWrjCv19I9n108Q= +github.com/jackc/puddle v1.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= @@ -134,49 +140,43 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/vlab-research/spine v0.0.1 h1:JyvhmaCpkheFurhONvSGrDR08W4JQ5IQOKv9H/xNMu4= -github.com/vlab-research/spine v0.0.1/go.mod h1:kq9zvGT26J9zBBuKyLh4U1krxfUkGd5jzhFmSmNMtxA= -github.com/vlab-research/spine v0.0.2 h1:EgN3iPWVaZNSqi7Hcsfn8yguZ5d//dsdSYCV/BaZUKA= -github.com/vlab-research/spine v0.0.2/go.mod h1:kq9zvGT26J9zBBuKyLh4U1krxfUkGd5jzhFmSmNMtxA= -github.com/vlab-research/spine v0.0.3 h1:3yRy+BpdQ090XKAABs/JdILe5XLNAWu4w9xFbYbdMeI= -github.com/vlab-research/spine v0.0.3/go.mod h1:kq9zvGT26J9zBBuKyLh4U1krxfUkGd5jzhFmSmNMtxA= -github.com/vlab-research/spine v0.0.4 h1:sJfRCMUumRM7HoQKBTlgV6Cna2QpNV/SEH9zc3ujMZA= -github.com/vlab-research/spine v0.0.4/go.mod h1:pYZvCHWpWnwPnTvHevLuHNSnggmUzU2fFirF+V6M5zM= -github.com/vlab-research/trans v0.0.2 h1:w9ft2X2V0diTXqQyD1TKRspkAtyGGMDsZNieEcbqPoI= -github.com/vlab-research/trans v0.0.2/go.mod h1:760R69NitmG7XcxEOF0OuuQjxvZiLGqG5sL493lmfjw= -github.com/vlab-research/trans v0.0.3 h1:rhen209AXL8i/XE2PgkU62YcXrFbUfROQnUW7Z4uVyY= -github.com/vlab-research/trans v0.0.3/go.mod h1:760R69NitmG7XcxEOF0OuuQjxvZiLGqG5sL493lmfjw= -github.com/vlab-research/trans v0.0.4 h1:ut9OWN5KW017Vn1eigq60xs6N+vrazWMnsP7C/H2TOk= -github.com/vlab-research/trans v0.0.4/go.mod h1:760R69NitmG7XcxEOF0OuuQjxvZiLGqG5sL493lmfjw= -github.com/vlab-research/trans v0.0.6 h1:ZZCWXru4xYwe8PZnLgp0KWB8nOGFZVJ8Yy4qTBQ4vio= -github.com/vlab-research/trans v0.0.6/go.mod h1:760R69NitmG7XcxEOF0OuuQjxvZiLGqG5sL493lmfjw= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/vlab-research/spine v0.0.5 h1:cvP/Ib4fssdgHPh9qzQd0xTD8eUdcsFq/viL/k2FH2M= +github.com/vlab-research/spine v0.0.5/go.mod h1:pYZvCHWpWnwPnTvHevLuHNSnggmUzU2fFirF+V6M5zM= +github.com/vlab-research/trans v0.0.8 h1:897LEi/sex1wRNhG2G8DKmzmLNuKB5torJNTiR7GNVI= +github.com/vlab-research/trans v0.0.8/go.mod h1:760R69NitmG7XcxEOF0OuuQjxvZiLGqG5sL493lmfjw= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -185,13 +185,22 @@ golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -199,19 +208,20 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/scribble/message_test.go b/scribble/message_test.go index 89665446..8d871cd5 100644 --- a/scribble/message_test.go +++ b/scribble/message_test.go @@ -2,26 +2,23 @@ package main import ( "testing" + "net/http" "time" "github.com/confluentinc/confluent-kafka-go/kafka" "github.com/stretchr/testify/assert" ) -func TestMessageWriterWritesGoodData(t *testing.T) { - pool := testPool() - defer pool.Close() +func before() { + http.Get("http://system/resetdb") +} - sql := `drop table if exists messages; - create table if not exists messages( - userid VARCHAR NOT NULL, - timestamp TIMESTAMPTZ NOT NULL, - content VARCHAR NOT NULL, - hsh INT AS (fnv64a(content)) STORED NOT NULL, - PRIMARY KEY (hsh, userid) - );` +func TestMessageWriterWritesGoodData(t *testing.T) { + before() - mustExec(t, pool, sql) + cfg := getConfig() + pool := getPool(cfg) + defer pool.Close() msgs := []*kafka.Message{ &kafka.Message{Value: []byte(`{ "foo": "bar "}`), Key: []byte("foo"), Timestamp: time.Now()}, @@ -34,24 +31,14 @@ func TestMessageWriterWritesGoodData(t *testing.T) { res := getCol(pool, "messages", "content") assert.Equal(t, len(res), 2) - - mustExec(t, pool, "drop table messages") } func TestMessageWriterDoesNotThrowOnDuplicateMessage(t *testing.T) { - pool := testPool() - defer pool.Close() - - sql := `drop table if exists messages; - create table if not exists messages( - userid VARCHAR NOT NULL, - timestamp TIMESTAMPTZ NOT NULL, - content VARCHAR NOT NULL, - hsh INT AS (fnv64a(content)) STORED NOT NULL, - PRIMARY KEY (hsh, userid) - );` + before() - mustExec(t, pool, sql) + cfg := getConfig() + pool := getPool(cfg) + defer pool.Close() msgs := []*kafka.Message{ &kafka.Message{Value: []byte(`{ "foo": "bar "}`), Key: []byte("foo"), Timestamp: time.Now()}, @@ -64,6 +51,4 @@ func TestMessageWriterDoesNotThrowOnDuplicateMessage(t *testing.T) { res := getCol(pool, "messages", "content") assert.Equal(t, len(res), 1) - - mustExec(t, pool, "drop table messages") } diff --git a/scribble/response_test.go b/scribble/response_test.go index b3a672b5..2b751dfd 100644 --- a/scribble/response_test.go +++ b/scribble/response_test.go @@ -8,116 +8,149 @@ import ( ) const ( - surveySql = `drop table if exists surveys; - create table if not exists surveys( - userid VARCHAR NOT NULL, - id UUID NOT NULL UNIQUE, - form_json JSON, - created TIMESTAMPTZ NOT NULL, - translation_conf JSON - );` - - insertSurveySql = `INSERT INTO surveys(userid, created, id, form_json, translation_conf) VALUES ('owner', NOW(), $1, $2, $3);` - - formA = `{"fields": [ - {"title": "What is your gender? ", - "ref": "eng_foo", - "properties": { - "choices": [{"label": "Male"}, - {"label": "Female"}, - {"label": "Other"}]}, - "type": "multiple_choice"}, - {"title": "Which state do you currently live in?\n- A. foo 91 bar\n- B. Jharkhand\n- C. Odisha\n- D. Uttar Pradesh", - "ref": "eng_bar", - "properties": {"choices": [{"label": "A"}, - {"label": "B"}, - {"label": "C"}, - {"label": "D"}]}, - "type": "multiple_choice"}, - {"title": "How old are you?", - "ref": "eng_baz", - "properties": {}, - "type": "number"}]}` - - formB = `{"title": "mytitle", "fields": [ - {"id": "vjl6LihKMtcX", - "title": "आपका लिंग क्या है? ", - "ref": "foo", - "properties": {"choices": [{"label": "पुरुष"}, - {"label": "महिला"}, - {"label": "अन्य"}]}, - "type": "multiple_choice"}, - {"id": "mdUpJMSY8Lct", - "title": "वर्तमान में आप किस राज्य में रहते हैं?\n- A. छत्तीसगढ़\n- B. झारखंड\n- C. ओडिशा\n- D. उत्तर प्रदेश", - "ref": "bar", - "properties": {"choices": [{"label": "A"}, - {"label": "B"}, - {"label": "C"}, - {"label": "D"}]}, - "type": "multiple_choice"}, - {"id": "mdUpJMSY8Lct", - "title": "वर्तमान में आप किस राज्य में रहते हैं?", - "ref": "baz", - "properties": {}, - "type": "number"}]}` - - responseSql = `drop table if exists surveys; - drop table if exists responses; - create table if not exists responses( - parent_shortcode VARCHAR NOT NULL, - surveyid UUID NOT NULL, - shortcode VARCHAR NOT NULL, - flowid INT NOT NULL, - userid VARCHAR NOT NULL, - pageid VARCHAR, - question_ref VARCHAR NOT NULL, - question_idx INT NOT NULL, - question_text VARCHAR NOT NULL, - response VARCHAR NOT NULL, - translated_response VARCHAR, - seed INT NOT NULL, - timestamp TIMESTAMPTZ NOT NULL, - metadata JSONB, - CONSTRAINT "valid_metadata" CHECK (json_typeof(metadata) = 'object'), - PRIMARY KEY (userid, timestamp, question_ref) - );` + surveyid = "00000000-0000-0000-0000-000000000000" + insertUser = ` + INSERT INTO users(id, email) + VALUES ('11111111-1111-1111-1111-111111111111', 'test@test.com'); + ` + insertSurvey = ` + INSERT INTO surveys(id, userid, form, formid, shortcode, title, created, translation_conf) + VALUES ($1, '11111111-1111-1111-1111-111111111111', $2, 'test-form-id', 'test-sc', 'test-title', NOW(), $3); + ` + insertCredentials = ` + INSERT INTO credentials(entity, key, details, userid) + VALUES ('facebook_page', 'foo', '{"id": "foo"}', '11111111-1111-1111-1111-111111111111'); + ` + formA = ` + { + "fields": [ + { + "title": "What is your gender?", + "ref": "eng_foo", + "properties": { + "choices": [ + { "label": "Male" }, + { "label": "Female" }, + { "label": "Other" } + ] + }, + "type": "multiple_choice" + }, + { + "title": "Which state do you currently live in?\n- A. foo 91 bar\n- B. Jharkhand\n- C. Odisha\n- D. Uttar Pradesh", + "ref": "eng_bar", + "properties": { + "choices": [ + { "label": "A" }, + { "label": "B" }, + { "label": "C" }, + { "label": "D" } + ] + }, + "type": "multiple_choice" + }, + { + "title": "How old are you?", + "ref": "eng_baz", + "properties": {}, + "type": "number" + } + ] + } + ` + formB = ` + { + "title": "mytitle", + "fields": [ + { + "id": "vjl6LihKMtcX", + "title": "आपका लिंग क्या है? ", + "ref": "foo", + "properties": { + "choices": [ + { "label": "पुरुष" }, + { "label": "महिला" }, + { "label": "अन्य" } + ] + }, + "type": "multiple_choice" + }, + { + "id": "mdUpJMSY8Lct", + "title": "वर्तमान में आप किस राज्य में रहते हैं?\n- A. छत्तीसगढ़\n- B. झारखंड\n- C. ओडिशा\n- D. उत्तर प्रदेश", + "ref": "bar", + "properties": { + "choices": [ + { "label": "A" }, + { "label": "B" }, + { "label": "C" }, + { "label": "D" } + ] + }, + "type": "multiple_choice" + }, + { + "id": "mdUpJMSY8Lct", + "title": "वर्तमान में आप किस राज्य में रहते हैं?", + "ref": "baz", + "properties": {}, + "type": "number" + } + ] + } + ` ) func TestResponseWriterWritesGoodData(t *testing.T) { - pool := testPool() + before() + + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - mustExec(t, pool, responseSql) + mustExec(t, pool, insertUser) + mustExec(t, pool, insertCredentials) + mustExec(t, pool, insertSurvey, surveyid, formA, `{}`) msgs := makeMessages([]string{ - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"foo", - "pageid": "baz", - "question_ref":"bar", - "question_idx":1, - "question_text":"foobar", - "response":"LOL", - "seed":858044518, - "metadata": {"foo":"bar","seed": 8978437}, - "timestamp":1599039840517}`, - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"bar", - "pageid": "baz", - "question_ref":"bar", - "question_idx":1, - "question_text":"foobar", - "response":"LOL", - "seed":858044518, - "metadata": {"foo":"bar","seed": 8978437}, - "timestamp":1599039840517}`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "11111111-1111-1111-1111-111111111111", + "pageid": "baz", + "question_ref": "bar", + "question_idx": 1, + "question_text": "foobar", + "response": "LOL", + "seed": 858044518, + "metadata": { + "foo": "bar", + "seed": 8978437 + }, + "timestamp": 1599039840517 + }`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "22222222-2222-2222-2222-2222222222222", + "pageid": "baz", + "question_ref": "bar", + "question_idx": 1, + "question_text": "foobar", + "response": "LOL", + "seed": 858044518, + "metadata": { + "foo": "bar", + "seed": 8978437 + }, + "timestamp": 1599039840517 + }`, }) writer := GetWriter(NewResponseScribbler(pool)) @@ -126,71 +159,89 @@ func TestResponseWriterWritesGoodData(t *testing.T) { res := getCol(pool, "responses", "userid") assert.Equal(t, 2, len(res)) - assert.Equal(t, "bar", *res[0]) - assert.Equal(t, "foo", *res[1]) + assert.Equal(t, "11111111-1111-1111-1111-111111111111", *res[0]) + assert.Equal(t, "22222222-2222-2222-2222-2222222222222", *res[1]) res = getCol(pool, "responses", "metadata->>'foo'") assert.Equal(t, 2, len(res)) assert.Equal(t, "bar", *res[0]) assert.Equal(t, "bar", *res[1]) - - mustExec(t, pool, "drop table responses") } func TestResponseWriterWritesNullPageIdIfNone(t *testing.T) { - pool := testPool() + before() + + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - mustExec(t, pool, responseSql) + mustExec(t, pool, insertUser) + mustExec(t, pool, insertCredentials) + mustExec(t, pool, insertSurvey, surveyid, formA, `{}`) msgs := makeMessages([]string{ - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"foo", - "question_ref":"bar", - "question_idx":1, - "question_text":"foobar", - "response":"LOL", - "seed":858044518, - "metadata": {"foo":"bar","seed": 8978437}, - "timestamp":1599039840517}`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "11111111-1111-1111-1111-111111111111", + "question_ref": "bar", + "question_idx": 1, + "question_text": "foobar", + "response": "LOL", + "seed": 858044518, + "metadata": { + "foo": "bar", + "seed": 8978437 + }, + "timestamp": 1599039840517 + }`, }) writer := GetWriter(NewResponseScribbler(pool)) err := writer.Write(msgs) assert.Nil(t, err) - rows, err := pool.Query(context.Background(), "select pageid from responses where pageid is null") + q := "SELECT pageid FROM responses WHERE pageid IS NULL" + rows, err := pool.Query(context.Background(), q) res := rowStrings(rows) assert.Equal(t, 1, len(res)) - mustExec(t, pool, "drop table responses") } func TestResponseWriterWritesPageIdIfExists(t *testing.T) { - pool := testPool() + before() + + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - mustExec(t, pool, responseSql) + mustExec(t, pool, insertUser) + mustExec(t, pool, insertCredentials) + mustExec(t, pool, insertSurvey, surveyid, formA, `{}`) msgs := makeMessages([]string{ - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"foo", - "pageid": "baz", - "question_ref":"bar", - "question_idx":1, - "question_text":"foobar", - "response":"LOL", - "seed":858044518, - "metadata": {"foo":"bar","seed": 8978437}, - "timestamp":1599039840517}`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "11111111-1111-1111-1111-111111111111", + "pageid": "baz", + "question_ref": "bar", + "question_idx": 1, + "question_text": "foobar", + "response": "LOL", + "seed": 858044518, + "metadata": { + "foo": "bar", + "seed": 8978437 + }, + "timestamp": 1599039840517 + }`, }) writer := GetWriter(NewResponseScribbler(pool)) @@ -200,59 +251,77 @@ func TestResponseWriterWritesPageIdIfExists(t *testing.T) { res := getCol(pool, "responses", "pageid") assert.Equal(t, 1, len(res)) assert.Equal(t, "baz", *res[0]) - - mustExec(t, pool, "drop table responses") } func TestResponseWriterHandlesMixedResponseAndShortCodeTypes(t *testing.T) { - pool := testPool() + before() + + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - mustExec(t, pool, responseSql) + mustExec(t, pool, insertUser) + mustExec(t, pool, insertCredentials) + mustExec(t, pool, insertSurvey, surveyid, formA, `{}`) msgs := makeMessages([]string{ - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"foo", - "pageid": "baz", - "question_ref":"bar", - "question_idx":1, - "question_text":"foobar", - "response":true, - "seed":858044518, - "metadata": {"foo":"bar","seed": 8978437}, - "timestamp":1599039840517}`, - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"foo", - "pageid": "baz", - "question_ref":"baz", - "question_idx":1, - "question_text":"foobar", - "response":"yes", - "seed":858044518, - "metadata": {"foo":"bar","seed": 8978437}, - "timestamp":1599039840517}`, - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":123, - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":123, - "flowid":1, - "userid":"foo", - "pageid": "baz", - "question_ref":"qux", - "question_idx":1, - "question_text":"foobar", - "response":25, - "seed":858044518, - "metadata": {"foo":"bar","seed": 8978437}, - "timestamp":1599039840517}`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "11111111-1111-1111-1111-111111111111", + "pageid": "baz", + "question_ref": "bar", + "question_idx": 1, + "question_text": "foobar", + "response": true, + "seed": 858044518, + "metadata": { + "foo": "bar", + "seed": 8978437 + }, + "timestamp": 1599039840517 + }`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "11111111-1111-1111-1111-111111111111", + "pageid": "baz", + "question_ref": "baz", + "question_idx": 1, + "question_text": "foobar", + "response": "yes", + "seed": 858044518, + "metadata": { + "foo": "bar", + "seed": 8978437 + }, + "timestamp": 1599039840518 + }`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": 123, + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": 123, + "flowid": 1, + "userid": "11111111-1111-1111-1111-111111111111", + "pageid": "baz", + "question_ref": "qux", + "question_idx": 1, + "question_text": "foobar", + "response": 25, + "seed": 858044518, + "metadata": { + "foo": "bar", + "seed": 8978437 + }, + "timestamp": 1599039840519 + }`, }) writer := GetWriter(NewResponseScribbler(pool)) @@ -261,38 +330,42 @@ func TestResponseWriterHandlesMixedResponseAndShortCodeTypes(t *testing.T) { res := getCol(pool, "responses", "response") assert.Equal(t, 3, len(res)) - assert.Equal(t, "true", *res[0]) - assert.Equal(t, "yes", *res[1]) - assert.Equal(t, "25", *res[2]) + assert.Equal(t, "25", *res[0]) + assert.Equal(t, "true", *res[1]) + assert.Equal(t, "yes", *res[2]) res = getCol(pool, "responses", "shortcode") assert.Equal(t, 3, len(res)) - assert.Equal(t, "baz", *res[0]) - assert.Equal(t, "123", *res[2]) - - mustExec(t, pool, "drop table responses") + assert.Equal(t, "123", *res[0]) + assert.Equal(t, "baz", *res[2]) } func TestResponseWriterFailsOnMissingData(t *testing.T) { - pool := testPool() - defer pool.Close() + before() - mustExec(t, pool, responseSql) + cfg := getConfig() + pool := getPool(cfg) + defer pool.Close() msgs := makeMessages([]string{ - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"foo", -"pageid": "baz", - "question_ref":"bar", - "question_idx":1, - "question_text":"foobar", - "seed":858044518, - "metadata": {"foo":"bar","seed": 8978437}, - "timestamp":1599039840517}`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "foo", + "pageid": "baz", + "question_ref": "bar", + "question_idx": 1, + "question_text": "foobar", + "seed": 858044518, + "metadata": { + "foo": "bar", + "seed": 8978437 + }, + "timestamp": 1599039840517 + }`, }) writer := GetWriter(NewResponseScribbler(pool)) @@ -301,29 +374,31 @@ func TestResponseWriterFailsOnMissingData(t *testing.T) { res := getCol(pool, "responses", "userid") assert.Equal(t, 0, len(res)) - mustExec(t, pool, "drop table responses") } func TestResponseWriterFailsOnMissingMetadata(t *testing.T) { - pool := testPool() - defer pool.Close() + before() - mustExec(t, pool, responseSql) + cfg := getConfig() + pool := getPool(cfg) + defer pool.Close() msgs := makeMessages([]string{ - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"foo", - "pageid": "baz", - "question_ref":"bar", - "question_idx":1, - "question_text":"foobar", - "response":"LOL", - "seed":858044518, - "timestamp":1599039840517}`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "foo", + "pageid": "baz", + "question_ref": "bar", + "question_idx": 1, + "question_text": "foobar", + "response": "LOL", + "seed": 858044518, + "timestamp": 1599039840517 + }`, }) writer := GetWriter(NewResponseScribbler(pool)) @@ -332,30 +407,32 @@ func TestResponseWriterFailsOnMissingMetadata(t *testing.T) { res := getCol(pool, "responses", "userid") assert.Equal(t, 0, len(res)) - mustExec(t, pool, "drop table responses") } func TestResponseWriterFailsIfMetadataFormatedPoorly(t *testing.T) { - pool := testPool() - defer pool.Close() + before() - mustExec(t, pool, responseSql) + cfg := getConfig() + pool := getPool(cfg) + defer pool.Close() msgs := makeMessages([]string{ - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"foo", - "pageid": "baz", - "question_ref":"bar", - "question_idx":1, - "question_text":"foobar", - "response":"LOL", - "seed":858044518, - "metadata":"{\"foo\":\"bar\",\"startTime\":1599039840517}", - "timestamp":1599039840517}`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "foo", + "pageid": "baz", + "question_ref": "bar", + "question_idx": 1, + "question_text": "foobar", + "response": "LOL", + "seed": 858044518, + "metadata": "{\"foo\":\"bar\",\"startTime\":1599039840517}", + "timestamp": 1599039840517 + }`, }) writer := GetWriter(NewResponseScribbler(pool)) @@ -364,31 +441,36 @@ func TestResponseWriterFailsIfMetadataFormatedPoorly(t *testing.T) { res := getCol(pool, "responses", "metadata->>'foo'") assert.Equal(t, 0, len(res)) - - mustExec(t, pool, "drop table responses") } func TestResponseWriterSucceedsIfMetadataEmpty(t *testing.T) { - pool := testPool() + before() + + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - mustExec(t, pool, responseSql) + mustExec(t, pool, insertUser) + mustExec(t, pool, insertCredentials) + mustExec(t, pool, insertSurvey, surveyid, formA, `{}`) msgs := makeMessages([]string{ - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"foo", - "pageid": "baz", - "question_ref":"bar", - "question_idx":1, - "question_text":"foobar", - "response":"LOL", - "seed":858044518, - "metadata":{}, - "timestamp":1599039840517}`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "foo", + "pageid": "baz", + "question_ref": "bar", + "question_idx": 1, + "question_text": "foobar", + "response": "LOL", + "seed": 858044518, + "metadata": {}, + "timestamp": 1599039840517 + }`, }) writer := GetWriter(NewResponseScribbler(pool)) @@ -397,45 +479,58 @@ func TestResponseWriterSucceedsIfMetadataEmpty(t *testing.T) { res := getCol(pool, "responses", "metadata->>'foo'") assert.Equal(t, 1, len(res)) - - mustExec(t, pool, "drop table responses") } func TestResponseWriterIgnoresRepeatMessages(t *testing.T) { - pool := testPool() + before() + + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - mustExec(t, pool, responseSql) + mustExec(t, pool, insertUser) + mustExec(t, pool, insertCredentials) + mustExec(t, pool, insertSurvey, surveyid, formA, `{}`) msgs := makeMessages([]string{ - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"foo", - "pageid": "baz", - "question_ref":"bar", - "question_idx":1, - "question_text":"foobar", - "response":"LOL", - "seed":858044518, - "metadata": {"foo":"bar","seed": 8978437}, - "timestamp":1599039840517}`, - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"foo", - "pageid": "baz", - "question_ref":"bar", - "question_idx":1, - "question_text":"foobar", - "response":"LOL", - "seed":858044518, - "metadata": {"foo":"bar","seed": 8978437}, - "timestamp":1599039840517}`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "foo", + "pageid": "baz", + "question_ref": "bar", + "question_idx": 1, + "question_text": "foobar", + "response": "LOL", + "seed": 858044518, + "metadata": { + "foo": "bar", + "seed": 8978437 + }, + "timestamp": 1599039840517 + }`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "foo", + "pageid": "baz", + "question_ref": "bar", + "question_idx": 1, + "question_text": "foobar", + "response": "LOL", + "seed": 858044518, + "metadata": { + "foo": "bar", + "seed": 8978437 + }, + "timestamp": 1599039840517 + }`, }) writer := GetWriter(NewResponseScribbler(pool)) @@ -445,62 +540,69 @@ func TestResponseWriterIgnoresRepeatMessages(t *testing.T) { res := getCol(pool, "responses", "userid") assert.Equal(t, 1, len(res)) assert.Equal(t, "foo", *res[0]) - - mustExec(t, pool, "drop table responses") } func TestResponseWriterTranslatesSuccesfullyToOtherForm(t *testing.T) { - pool := testPool() + before() + + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - mustExec(t, pool, responseSql) - mustExec(t, pool, surveySql) - mustExec(t, pool, insertSurveySql, "25d88630-8b7b-4f2b-8630-4e5f9085e888", formA, `{}`) - mustExec(t, pool, insertSurveySql, "d6c21c81-fcd0-4aa4-8975-8584d8bdb820", formB, `{"destination": "25d88630-8b7b-4f2b-8630-4e5f9085e888"}`) + mustExec(t, pool, insertUser) + mustExec(t, pool, insertCredentials) + mustExec(t, pool, insertSurvey, "88888888-8888-8888-8888-888888888888", formA, `{}`) + mustExec(t, pool, insertSurvey, surveyid, formB, `{"destination": "88888888-8888-8888-8888-888888888888"}`) msgs := makeMessages([]string{ - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"bar", - "pageid": "baz", - "question_ref":"bar", - "question_idx":1, - "question_text":"foobar", - "response":"LOL", - "seed":858044518, - "metadata":{}, - "timestamp":1599039840517}`, - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"bar", - "pageid": "baz", - "question_ref":"bar", - "question_idx":1, - "question_text":"foobar", - "response":"A", - "seed":858044518, - "metadata":{}, - "timestamp":1999099840999}`, - `{"parent_surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "parent_shortcode":"baz", - "surveyid":"d6c21c81-fcd0-4aa4-8975-8584d8bdb820", - "shortcode":"baz", - "flowid":1, - "userid":"bar", - "pageid": "baz", - "question_ref":"foo", - "question_idx":1, - "question_text":"foobar", - "response":"अन्य", - "seed":858044518, - "metadata":{}, - "timestamp":1999099840999}`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "bar", + "pageid": "baz", + "question_ref": "bar", + "question_idx": 1, + "question_text": "foobar", + "response": "LOL", + "seed": 858044518, + "metadata": {}, + "timestamp": 1599039840517 + }`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "bar", + "pageid": "baz", + "question_ref": "bar", + "question_idx": 1, + "question_text": "foobar", + "response": "A", + "seed": 858044518, + "metadata": {}, + "timestamp": 1999099840999 + }`, + `{ + "parent_surveyid": "00000000-0000-0000-0000-000000000000", + "parent_shortcode": "baz", + "surveyid": "00000000-0000-0000-0000-000000000000", + "shortcode": "baz", + "flowid": 1, + "userid": "bar", + "pageid": "baz", + "question_ref": "foo", + "question_idx": 1, + "question_text": "foobar", + "response": "अन्य", + "seed": 858044518, + "metadata": {}, + "timestamp": 1999099840999 + }`, }) writer := GetWriter(NewResponseScribbler(pool)) @@ -512,8 +614,8 @@ func TestResponseWriterTranslatesSuccesfullyToOtherForm(t *testing.T) { res := getCol(pool, "responses", "response") assert.Equal(t, 3, len(res)) - assert.Equal(t, "LOL", *res[0]) - assert.Equal(t, "A", *res[1]) + assert.Equal(t, "A", *res[0]) + assert.Equal(t, "LOL", *res[1]) assert.Equal(t, "अन्य", *res[2]) res = getCol(pool, "responses", "translated_response") @@ -522,6 +624,4 @@ func TestResponseWriterTranslatesSuccesfullyToOtherForm(t *testing.T) { assert.Nil(t, res[0]) assert.Equal(t, "foo 91 bar", *res[1]) assert.Equal(t, "Other", *res[2]) - - mustExec(t, pool, "drop table responses") } diff --git a/scribble/scribble.go b/scribble/scribble.go index ce849819..2586331c 100644 --- a/scribble/scribble.go +++ b/scribble/scribble.go @@ -4,29 +4,11 @@ import ( "context" "fmt" "log" - "time" - "github.com/caarlos0/env/v6" "github.com/jackc/pgx/v4/pgxpool" "github.com/vlab-research/spine" ) -type Config struct { - Db string `env:"CHATBASE_DATABASE,required"` - User string `env:"CHATBASE_USER,required"` - Password string `env:"CHATBASE_PASSWORD,required"` - Host string `env:"CHATBASE_HOST,required"` - Port string `env:"CHATBASE_PORT,required"` - KafkaBrokers string `env:"KAFKA_BROKERS,required"` - KafkaPollTimeout time.Duration `env:"KAFKA_POLL_TIMEOUT,required"` - Topic string `env:"KAFKA_TOPIC,required"` - Group string `env:"KAFKA_GROUP,required"` - BatchSize int `env:"SCRIBBLE_BATCH_SIZE,required"` - ChunkSize int `env:"SCRIBBLE_CHUNK_SIZE,required"` - Destination string `env:"SCRIBBLE_DESTINATION,required"` - Handlers string `env:"SCRIBBLE_ERROR_HANDLERS,required"` -} - func monitor(errs <-chan error) { e := <-errs log.Fatalf("Scribble failed with error: %v", e) @@ -39,11 +21,11 @@ func handle(err error) { } func getPool(cfg *Config) *pgxpool.Pool { - conString := fmt.Sprintf("postgresql://%s@%s:%s/%s?sslmode=disable", cfg.User, cfg.Host, cfg.Port, cfg.Db) - config, err := pgxpool.ParseConfig(conString) + con := fmt.Sprintf("postgresql://%s@%s:%d/%s?sslmode=disable", cfg.DbUser, cfg.DbHost, cfg.DbPort, cfg.DbName) + config, err := pgxpool.ParseConfig(con) handle(err) - config.MaxConns = int32(32) + config.MaxConns = int32(cfg.DbMaxConns) ctx := context.Background() pool, err := pgxpool.ConnectConfig(ctx, config) @@ -68,32 +50,20 @@ func getMarshaller(cfg *Config, pool *pgxpool.Pool) Scribbler { return fn(pool) } -func getConfig() Config { - cfg := Config{} - err := env.Parse(&cfg) - handle(err) - if cfg.Handlers != "" && cfg.ChunkSize != 1 { - log.Fatalf("Scribble can only pass on errors with a chunk size of 1. Passed chunk size: %v", - cfg.ChunkSize) - } - return cfg -} - func main() { cfg := getConfig() - - pool := getPool(&cfg) + pool := getPool(cfg) c := spine.NewKafkaConsumer(cfg.Topic, cfg.KafkaBrokers, cfg.Group, cfg.KafkaPollTimeout, cfg.BatchSize, cfg.ChunkSize) // monitor errors, with handling as per config errs := make(chan error) - go monitor(HandleErrors(errs, getHandlers(&cfg))) + go monitor(HandleErrors(errs, getHandlers(cfg))) // Write forever // getwriter takes the struct, not marshalwriteable - writer := GetWriter(getMarshaller(&cfg, pool)) + writer := GetWriter(getMarshaller(cfg, pool)) for { c.SideEffect(writer.Write, errs) } diff --git a/scribble/state_test.go b/scribble/state_test.go index 8c1820bc..64a5b87e 100644 --- a/scribble/state_test.go +++ b/scribble/state_test.go @@ -10,52 +10,43 @@ import ( "github.com/vlab-research/spine" ) -const ( - stateSql = ` - drop table if exists states; - drop table if exists credentials; - - create table if not exists credentials( - entity VARCHAR NOT NULL, - key VARCHAR NOT NULL UNIQUE, - created TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, - details JSONB NOT NULL, - facebook_page_id VARCHAR AS (CASE WHEN entity = 'facebook_page' THEN details->>'id' ELSE NULL END) STORED, - UNIQUE(entity, key), - UNIQUE(facebook_page_id) - ); - - insert into credentials(entity, key, details) values('facebook_page', 'foo', '{"id": "foo"}'); - - create table if not exists states( - userid VARCHAR NOT NULL, - pageid VARCHAR NOT NULL NOT NULL REFERENCES credentials(facebook_page_id), - updated TIMESTAMPTZ NOT NULL, - current_state VARCHAR NOT NULL, - state_json JSON NOT NULL, - CONSTRAINT "valid_state_json" CHECK (state_json ? 'state'), - PRIMARY KEY (userid, pageid) - );` -) - func TestStateWriterWritesGoodData(t *testing.T) { - pool := testPool() + before() + + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - mustExec(t, pool, stateSql) - mustExec(t, pool, stateSql) + mustExec(t, pool, insertUser) + mustExec(t, pool, insertCredentials) msgs := makeMessages([]string{ - `{"userid": "bar", - "pageid": "foo", - "updated": 1598706047838, - "current_state": "QOUT", - "state_json": { "token": "bar", "state": "QOUT", "tokens": ["foo"]}}`, - `{"userid": "baz", - "pageid": "foo", - "updated": 1598706047838, - "current_state": "RESPONDING", - "state_json": { "token": "bar", "state": "QOUT", "tokens": ["foo"]}}`, + `{ + "userid": "bar", + "pageid": "foo", + "updated": 1598706047838, + "current_state": "QOUT", + "state_json": { + "token": "bar", + "state": "QOUT", + "tokens": [ + "foo" + ] + } + }`, + `{ + "userid": "baz", + "pageid": "foo", + "updated": 1598706047838, + "current_state": "RESPONDING", + "state_json": { + "token": "bar", + "state": "QOUT", + "tokens": [ + "foo" + ] + } + }`, }) writer := GetWriter(NewStateScribbler(pool)) @@ -67,28 +58,45 @@ func TestStateWriterWritesGoodData(t *testing.T) { assert.Equal(t, "bar", *res[0]) assert.Equal(t, "bar", *res[1]) - - mustExec(t, pool, "drop table states") } func TestStateWriterOverwritesOnePersonsState(t *testing.T) { - pool := testPool() + before() + + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - mustExec(t, pool, stateSql) - mustExec(t, pool, stateSql) + mustExec(t, pool, insertUser) + mustExec(t, pool, insertCredentials) msgs := makeMessages([]string{ - `{"userid": "bar", - "pageid": "foo", - "updated": 1598706047838, - "current_state": "QOUT", - "state_json": { "token": "bar", "state": "QOUT", "tokens": ["foo"]}}`, - `{"userid": "bar", - "pageid": "foo", - "updated": 1598706047838, - "current_state": "RESPONDING", - "state_json": { "token": "bar", "state": "QOUT", "tokens": ["foo"]}}`, + `{ + "userid": "bar", + "pageid": "foo", + "updated": 1598706047838, + "current_state": "QOUT", + "state_json": { + "token": "bar", + "state": "QOUT", + "tokens": [ + "foo" + ] + } + }`, + `{ + "userid": "bar", + "pageid": "foo", + "updated": 1598706047838, + "current_state": "RESPONDING", + "state_json": { + "token": "bar", + "state": "QOUT", + "tokens": [ + "foo" + ] + } + }`, }) writer := GetWriter(NewStateScribbler(pool)) @@ -99,35 +107,52 @@ func TestStateWriterOverwritesOnePersonsState(t *testing.T) { assert.Equal(t, len(res), 1) assert.Equal(t, "RESPONDING", *res[0]) - - mustExec(t, pool, "drop table states") } func TestStateWriterOverwritesOnePersonsStateIgnoresUpdatedTimeOverwritesWithLatest(t *testing.T) { - pool := testPool() + before() + + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - mustExec(t, pool, stateSql) - mustExec(t, pool, stateSql) + mustExec(t, pool, insertUser) + mustExec(t, pool, insertCredentials) msgs := makeMessages([]string{ - `{"userid": "bar", - "pageid": "foo", - "updated": 1598706047838, - "current_state": "QOUT", - "state_json": { "token": "bar", "state": "QOUT", "tokens": ["foo"]}}`, - `{"userid": "bar", - "pageid": "foo", - "updated": 1598706035000, - "current_state": "RESPONDING", - "state_json": { "token": "bar", "state": "QOUT", "tokens": ["foo"]}}`, + `{ + "userid": "bar", + "pageid": "foo", + "updated": 1598706047838, + "current_state": "QOUT", + "state_json": { + "token": "bar", + "state": "QOUT", + "tokens": [ + "foo" + ] + } + }`, + `{ + "userid": "bar", + "pageid": "foo", + "updated": 1598706035000, + "current_state": "RESPONDING", + "state_json": { + "token": "bar", + "state": "QOUT", + "tokens": [ + "foo" + ] + } + }`, }) writer := GetWriter(NewStateScribbler(pool)) err := writer.Write(msgs) assert.Nil(t, err) - rows, err := pool.Query(context.Background(), "select updated from states") + rows, err := pool.Query(context.Background(), "SELECT updated FROM states") assert.Nil(t, err) for rows.Next() { @@ -136,27 +161,44 @@ func TestStateWriterOverwritesOnePersonsStateIgnoresUpdatedTimeOverwritesWithLat assert.Nil(t, err) assert.Equal(t, int64(1598706035), col.Unix()) } - - mustExec(t, pool, "drop table states") } func TestStateWriterFailsOnBadDataInOneRecordValidationHandler(t *testing.T) { - pool := testPool() + before() + + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - mustExec(t, pool, stateSql) + mustExec(t, pool, insertUser) + mustExec(t, pool, insertCredentials) msgs := makeMessages([]string{ - `{"userid": "bar", - "pageid": "foo", - "updated": 1598706047838, - "state_json": { "token": "bar", "state": "QOUT", "tokens": ["foo"]}}`, - - `{"userid": "baz", - "pageid": "foo", - "updated": 1598706047838, - "current_state": "RESPONDING", - "state_json": { "token": "bar", "state": "QOUT", "tokens": ["foo"]}}`, + `{ + "userid": "bar", + "pageid": "foo", + "updated": 1598706047838, + "state_json": { + "token": "bar", + "state": "QOUT", + "tokens": [ + "foo" + ] + } + }`, + `{ + "userid": "baz", + "pageid": "foo", + "updated": 1598706047838, + "current_state": "RESPONDING", + "state_json": { + "token": "bar", + "state": "QOUT", + "tokens": [ + "foo" + ] + } + }`, }) writer := GetWriter(NewStateScribbler(pool)) @@ -172,22 +214,26 @@ func TestStateWriterFailsOnBadDataInOneRecordValidationHandler(t *testing.T) { res := getCol(pool, "states", "state_json->>'token'") assert.Equal(t, len(res), 0) - - mustExec(t, pool, "drop table states") } func TestStateWriterFailsOnMissingState(t *testing.T) { - pool := testPool() + before() + + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - mustExec(t, pool, stateSql) + mustExec(t, pool, insertUser) + mustExec(t, pool, insertCredentials) msgs := makeMessages([]string{ - `{"userid": "baz", - "pageid": "foo", - "updated": 1598706047838, - "current_state": "RESPONDING", - "state_json": {}}`, + `{ + "userid": "baz", + "pageid": "foo", + "updated": 1598706047838, + "current_state": "RESPONDING", + "state_json": {} + }`, }) writer := GetWriter(NewStateScribbler(pool)) @@ -199,22 +245,29 @@ func TestStateWriterFailsOnMissingState(t *testing.T) { res := getCol(pool, "states", "state_json->>'token'") assert.Equal(t, len(res), 0) - - mustExec(t, pool, "drop table states") } func TestStateWriterFailsStateViolatesFacebookPageConstraintHandledByForeignKeyHandler(t *testing.T) { - pool := testPool() - defer pool.Close() + before() - mustExec(t, pool, stateSql) + cfg := getConfig() + pool := getPool(cfg) + defer pool.Close() msgs := makeMessages([]string{ - `{"userid": "baz", - "pageid": "notapage", - "updated": 1598706047838, - "current_state": "RESPONDING", - "state_json": { "token": "bar", "state": "QOUT", "tokens": ["foo"]}}`, + `{ + "userid": "baz", + "pageid": "notapage", + "updated": 1598706047838, + "current_state": "RESPONDING", + "state_json": { + "token": "bar", + "state": "QOUT", + "tokens": [ + "foo" + ] + } + }`, }) writer := GetWriter(NewStateScribbler(pool)) @@ -227,40 +280,64 @@ func TestStateWriterFailsStateViolatesFacebookPageConstraintHandledByForeignKeyH res := getCol(pool, "states", "state_json->>'token'") assert.Equal(t, len(res), 0) - - mustExec(t, pool, "drop table states") } func TestStateWriterWithHandlersIntegration(t *testing.T) { - pool := testPool() + before() + + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - mustExec(t, pool, stateSql) + mustExec(t, pool, insertUser) + mustExec(t, pool, insertCredentials) msgs := makeMessages([]string{ - `{"userid": "bar", - "pageid": "foo", - "updated": 1598706047838, - "state_json": { "token": "bar", "state": "QOUT", "tokens": ["foo"]}}`, - `{"userid": "baz", - "pageid": "foo", - "updated": 1598706047838, - "current_state": "RESPONDING", - "state_json": { "token": "baz", "state": "QOUT", "tokens": ["foo"]}}`, - `{"userid": "baz", - "pageid": "notapage", - "updated": 1598706047838, - "current_state": "RESPONDING", - "state_json": { "token": "qux", "state": "QOUT", "tokens": ["foo"]}}`, + `{ + "userid": "bar", + "pageid": "foo", + "updated": 1598706047838, + "state_json": { + "token": "bar", + "state": "QOUT", + "tokens": [ + "foo" + ] + } + }`, + `{ + "userid": "baz", + "pageid": "foo", + "updated": 1598706047838, + "current_state": "RESPONDING", + "state_json": { + "token": "baz", + "state": "QOUT", + "tokens": [ + "foo" + ] + } + }`, + `{ + "userid": "baz", + "pageid": "notapage", + "updated": 1598706047838, + "current_state": "RESPONDING", + "state_json": { + "token": "qux", + "state": "QOUT", + "tokens": [ + "foo" + ] + } + }`, }) writer := GetWriter(NewStateScribbler(pool)) c := &spine.TestConsumer{Messages: msgs, Commits: 0} - consumer := spine.KafkaConsumer{c, time.Second, 3, 1} errs := make(chan error) - mainErrors := HandleErrors(errs, getHandlers(&Config{Handlers: "validation,foreignkey"})) go func() { for e := range mainErrors { @@ -271,6 +348,4 @@ func TestStateWriterWithHandlersIntegration(t *testing.T) { consumer.SideEffect(writer.Write, errs) res := getCol(pool, "states", "state_json->>'token'") assert.Equal(t, 1, len(res)) - - mustExec(t, pool, "drop table states") } diff --git a/scribble/test.yaml b/scribble/test.yaml new file mode 100644 index 00000000..2389f69e --- /dev/null +++ b/scribble/test.yaml @@ -0,0 +1,93 @@ +version: '3' + +services: + main: + depends_on: + - system + image: ${APP_NAME}_dev + build: + context: . + dockerfile: Dockerfile.dev + environment: + CHATBASE_DATABASE: chatroach + CHATBASE_HOST: cockroachdb + CHATBASE_PORT: 26257 + CHATBASE_USER: root + CHATBASE_MAX_CONNECTIONS: 1 + KAFKA_BROKERS: "" + KAFKA_POLL_TIMEOUT: "" + KAFKA_TOPIC: "" + KAFKA_GROUP: "" + SCRIBBLE_BATCH_SIZE: "" + SCRIBBLE_CHUNK_SIZE: "" + SCRIBBLE_DESTINATION: "" + SCRIBBLE_ERROR_HANDLERS: "" + command: | + sh -c ' + echo "Running tests..." + go mod tidy + + if [ -z "${ARG}" ] + then + nodemon \ + --ext "*" \ + --exec "go test -cover -tags dynamic" + fi + + if [ "${ARG}" = "--is-ci" ] + then + go test -cover -tags dynamic + exit + fi + + nodemon \ + --ext "*" \ + --exec "go test -cover -tags dynamic -run ${ARG}" + ' + volumes: + - ./:/app + networks: + - fly + system: + build: + context: ../system + environment: + CHATBASE_DATABASE: chatroach + CHATBASE_HOST: cockroachdb + CHATBASE_PORT: 26257 + CHATBASE_USER: root + PORT: 80 + command: go run . + ports: + - 80:80 + volumes: + - ../system:/app + networks: + - fly + initdb: + image: cockroachdb/cockroach:v20.1.4 + depends_on: + - cockroachdb + entrypoint: | + sh -c ' + /tools/wait-for-it.sh cockroachdb:26257 -t 60 + cat /migrations/* > /tmp/merged-latest.sql + cat /tmp/merged-latest.sql | ./cockroach sql --insecure --host cockroachdb + echo "set sql_safe_updates=false;" | ./cockroach sql --insecure --host cockroachdb + ' + volumes: + - ../devops:/tools + - ../devops/sql:/migrations + networks: + - fly + cockroachdb: + image: cockroachdb/cockroach:v20.1.4 + command: start --insecure + ports: + - 26257:26257 + networks: + - fly + +networks: + fly: + driver: bridge diff --git a/scribble/test_helpers.go b/scribble/test_helpers.go index 6df7ee39..f15039f5 100644 --- a/scribble/test_helpers.go +++ b/scribble/test_helpers.go @@ -33,7 +33,8 @@ func rowStrings(rows pgx.Rows) []*string { } func getCol(pool *pgxpool.Pool, table string, col string) []*string { - rows, err := pool.Query(context.Background(), fmt.Sprintf("select %v from %v", col, table)) + q := fmt.Sprintf("SELECT %v FROM %v", col, table) + rows, err := pool.Query(context.Background(), q) if err != nil { panic(err) } @@ -48,14 +49,3 @@ func mustExec(t testing.TB, conn *pgxpool.Pool, sql string, arguments ...interfa } return } - -func testPool() *pgxpool.Pool { - config, err := pgxpool.ParseConfig("postgres://root@localhost:5433/test") - handle(err) - - ctx := context.Background() - pool, err := pgxpool.ConnectConfig(ctx, config) - handle(err) - - return pool -} diff --git a/scribble/write_test.go b/scribble/write_test.go index ff1a2185..819c84e5 100644 --- a/scribble/write_test.go +++ b/scribble/write_test.go @@ -68,15 +68,16 @@ func TestPrepWhenOneBadYouGetAnError(t *testing.T) { } func TestWriteBatchSucceeds(t *testing.T) { - - pool := testPool() + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - sql := `drop table if exists test; - create table if not exists test( - foo varchar - );` - + sql := ` + DROP TABLE IF EXISTS test; + CREATE TABLE IF NOT EXISTS test( + foo varchar + ); + ` mustExec(t, pool, sql) msgs := []*kafka.Message{ @@ -89,7 +90,7 @@ func TestWriteBatchSucceeds(t *testing.T) { err := writer.Write(msgs) assert.Nil(t, err) - rows, err := pool.Query(context.Background(), "select * from test") + rows, err := pool.Query(context.Background(), "SELECT * FROM test") handle(err) results := []string{} @@ -105,14 +106,16 @@ func TestWriteBatchSucceeds(t *testing.T) { } func TestWriteBatchWithFailedLocallyWritesNothing(t *testing.T) { - pool := testPool() + cfg := getConfig() + pool := getPool(cfg) defer pool.Close() - sql := `drop table if exists test; - create table if not exists test( - foo varchar - );` - + sql := ` + DROP TABLE IF EXISTS test; + CREATE TABLE IF NOT EXISTS test( + foo varchar + ); + ` mustExec(t, pool, sql) msgs := []*kafka.Message{ @@ -125,7 +128,7 @@ func TestWriteBatchWithFailedLocallyWritesNothing(t *testing.T) { err := writer.Write(msgs) assert.NotNil(t, err) - rows, err := pool.Query(context.Background(), "select * from test") + rows, err := pool.Query(context.Background(), "SELECT * FROM test") handle(err) results := []string{} diff --git a/test.sh b/test.sh index e1b700c5..336ba5c2 100755 --- a/test.sh +++ b/test.sh @@ -1,14 +1,19 @@ export APP_NAME=${1} +export ARG=${2} + if [ "${APP_NAME}" = "" ] then echo "ERROR: enter an application name" exit 1 fi - FILE_PATH="${APP_NAME}/test.yaml" -export IS_CI=${2} -docker-compose -f ${FILE_PATH} down --remove-orphans +function cleanup { + docker-compose -f ${FILE_PATH} down --remove-orphans +} + +trap cleanup EXIT +cleanup docker-compose -f ${FILE_PATH} build initdb docker-compose -f ${FILE_PATH} run initdb