diff --git a/.deadlines.yml b/.deadlines.yml deleted file mode 100644 index 34f7a51..0000000 --- a/.deadlines.yml +++ /dev/null @@ -1,190 +0,0 @@ -- group: Bonus - start: 30-09-2023 14:00 - deadline: 18-02-2024 23:59 - tasks: - - task: consistenthash - score: 200 - - task: gossip - score: 300 - - task: smartsched - score: 200 - watch: - - distbuild/pkg/scheduler - - task: wasm - score: 300 - -- group: Analysis - start: 30-09-2023 14:00 - deadline: 11-02-2023 23:59 - tasks: - - task: testifycheck - score: 200 - - task: gzep - score: 100 - -- group: "[HW] Dist Build" - start: 30-09-2023 14:00 - deadline: 04-02-2024 23:59 - tasks: - - task: distbuild - score: 0 - -- group: Low level - start: 30-09-2023 14:00 - deadline: 28-01-2024 23:59 - tasks: - - task: illegal - score: 100 - - task: blowfish - score: 100 - -- group: Reflect - start: 30-09-2023 14:00 - deadline: 21-01-2024 23:59 - tasks: - - task: reversemap - score: 100 - - task: jsonlist - score: 100 - - task: jsonrpc - score: 100 - - task: structtags - score: 100 - -- group: SQL - start: 30-09-2023 14:00 - deadline: 31-12-2023 23:59 - tasks: - - task: dao - score: 100 - - task: ledger - score: 200 - - task: shopfront - score: 100 - - task: wscat - score: 200 - -- group: Generics - start: 30-09-2023 14:00 - deadline: 24-12-2023 23:59 - tasks: - - task: genericsum - score: 100 - - task: treeiter - score: 100 - - task: coverme - score: 300 - -- group: HTTP - start: 30-09-2023 14:00 - deadline: 17-12-2023 23:59 - tasks: - - task: urlshortener - score: 100 - - task: digitalclock - score: 100 - - task: middleware - score: 200 - - task: olympics - score: 200 - - task: firewall - score: 200 - -- group: Concurrency with shared memory - start: 30-09-2023 14:00 - deadline: 03-12-2023 23:59 - tasks: - - task: dupcall - score: 200 - - task: keylock - score: 200 - - task: batcher - score: 200 - - task: pubsub - score: 300 - -- group: Testing - start: 30-09-2023 14:00 - deadline: 26-11-2023 23:59 - tasks: - - task: testequal - score: 100 - - task: fileleak - score: 100 - - task: tabletest - score: 100 - - task: tparallel - score: 200 - - task: iprange - score: 100 - -- group: "[HW] Gitfame" - start: 30-09-2023 14:00 - deadline: 19-11-2023 23:59 - tasks: - - task: gitfame - score: 0 - -- group: Goroutines - start: 30-09-2023 14:00 - deadline: 05-11-2023 23:59 - tasks: - - task: tour1 - score: 100 - - task: once - score: 100 - - task: rwmutex - score: 100 - - task: waitgroup - score: 100 - - task: cond - score: 100 - - task: ratelimit - score: 100 - -- group: Interfaces - start: 30-09-2023 14:00 - deadline: 29-10-2023 23:59 - tasks: - - task: otp - score: 100 - - task: lrucache - score: 100 - - task: externalsort - score: 100 - - task: retryupdate - score: 100 - - task: ciletters - score: 100 - -- group: Basics - start: 30-09-2023 14:00 - deadline: 22-10-2023 23:59 - tasks: - - task: hotelbusiness - score: 100 - - task: hogwarts - score: 100 - - task: utf8 - score: 100 - - task: varfmt - score: 100 - - task: speller - score: 100 - - task: forth - score: 100 - -- group: Hello World - start: 30-09-2023 14:00 - deadline: 15-10-2023 23:59 - tasks: - - task: sum - score: 100 - - task: tour0 - score: 100 - - task: wordcount - score: 100 - - task: urlfetch - score: 100 - - task: fetchall - score: 100 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b2397cd..54626b1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,11 +1,7 @@ grade: - image: cr.yandex/crp9onavos88ug32d5r2/grader/go - variables: - DOCKER_HOST: tcp://docker:2375/ - DOCKER_TLS_CERTDIR: "" - APP_HOST: docker - # services: - #- docker:dind + tags: + - experimental + image: gitlab.manytask.org:5050/go/public-2024-spring script: - testtool grade timeout: 10 minutes diff --git a/.manytask.yml b/.manytask.yml new file mode 100644 index 0000000..5f23d6f --- /dev/null +++ b/.manytask.yml @@ -0,0 +1,263 @@ +version: 1 + + +settings: # required + course_name: go + + gitlab_base_url: https://gitlab.manytask.org + public_repo: go/public-2024-spring + students_group: go/students-2024-spring + + +ui: + task_url_template: https://github.com/slon/shad-go/tree/main/$TASK_NAME + + # optional, any number of links + links: + "TG Channel": https://t.me/+eb5z6ZS-sI8xZDNi + "TG Chat": https://t.me/+Tk8VTMAk5Tlp7Txm + "LMS": https://lk.yandexdataschool.ru/ + "Contribute Manytask": https://github.com/manytask + + +deadlines: + timezone: Europe/Moscow + + deadlines: hard # hard/interpolate + # max_submissions: 10 # optional + # submission_penalty: 0.1 # optional + + schedule: + - group: Hello World + start: 2024-01-01 18:00 + steps: + 0.3: 2024-02-27 23:59 + end: 2024-07-10 23:59 + tasks: + - task: sum + score: 100 + - task: tour0 + score: 100 + - task: wordcount + score: 100 + - task: urlfetch + score: 100 + - task: fetchall + score: 100 + + - group: Basics + start: 2024-02-24 13:00 + steps: + 0.3: 2024-03-06 06:00 + end: 2024-07-10 23:59 + tasks: + - task: hotelbusiness + score: 100 + - task: hogwarts + score: 100 + - task: utf8 + score: 100 + - task: varfmt + score: 100 + - task: speller + score: 100 + - task: forth + score: 100 + + - group: Interfaces + start: 2024-03-02 13:00 + steps: + 0.3: 2024-03-12 23:59 + end: 2024-07-10 23:59 + tasks: + - task: otp + score: 100 + - task: retryupdate + score: 100 + - task: lrucache + score: 100 + - task: externalsort + score: 100 + - task: ciletters + score: 100 + + - group: Goroutines + start: 2024-03-03 13:00 + steps: + 0.3: 2024-03-19 23:59 + end: 2024-07-10 23:59 + tasks: + - task: tour1 + score: 100 + - task: once + score: 100 + - task: rwmutex + score: 100 + - task: waitgroup + score: 100 + - task: cond + score: 100 + - task: ratelimit + score: 100 + + - group: "[HW] Gitfame" + start: 2024-03-09 13:00 + end: 2024-03-24 23:59 + tasks: + - task: gitfame + score: 0 + + - group: Testing + start: 2024-03-16 13:00 + steps: + 0.3: 2024-03-27 23:59 + end: 2024-07-10 23:59 + tasks: + - task: testequal + score: 100 + - task: fileleak + score: 100 + - task: tabletest + score: 100 + - task: tparallel + score: 200 + - task: iprange + score: 100 + + - group: Concurrency with shared memory + start: 2024-03-30 13:00 + steps: + 0.3: 2024-04-10 23:59 + end: 2024-07-10 23:59 + tasks: + - task: dupcall + score: 200 + - task: keylock + score: 200 + - task: batcher + score: 200 + - task: pubsub + score: 300 + + - group: HTTP + start: 2024-04-06 13:00 + steps: + 0.3: 2024-04-16 23:59 + end: 2024-07-10 23:59 + tasks: + - task: urlshortener + score: 100 + - task: digitalclock + score: 100 + - task: middleware + score: 200 + - task: firewall + score: 200 + - task: olympics + score: 200 + + - group: SQL + start: 2024-04-13 13:00 + steps: + 0.3: 2024-04-23 23:59 + end: 2024-07-10 23:59 + tasks: + - task: dao + score: 100 + - task: ledger + score: 200 + - task: shopfront + score: 100 + - task: wscat + score: 200 + + - group: "[HW] Dist Build" + start: 2024-04-13 13:00 + end: 2024-05-13 23:59 + tasks: + - task: distbuild + score: 1 + + - group: Generics + start: 2024-04-20 13:00 + steps: + 0.3: 2024-05-02 23:59 + end: 2024-07-10 23:59 + tasks: + - task: genericsum + score: 100 + - task: treeiter + score: 100 + - task: coverme + score: 300 + + - group: Reflect + start: 2024-04-27 13:00 + steps: + 0.3: 2024-05-07 23:59 + end: 2024-07-10 23:59 + tasks: + - task: reversemap + score: 100 + - task: jsonlist + score: 100 + - task: jsonrpc + score: 100 + - task: structtags + score: 100 + + - group: Low level + start: 2024-05-04 13:00 + steps: + 0.3: 2024-05-14 23:59 + end: 2024-07-10 23:59 + tasks: + - task: illegal + score: 100 + - task: blowfish + score: 100 + - task: gzep + score: 100 + + - group: Analysis + start: 2024-05-11 13:00 + steps: + 0.3: 2024-05-21 23:59 + end: 2024-07-10 23:59 + tasks: + - task: testifycheck + score: 200 + + - group: Bonus + start: 2024-03-03 13:00 + end: 2024-07-10 23:59 + tasks: + - task: yamlembed + is_bonus: true + score: 100 + - task: consistenthash + is_bonus: true + score: 200 + - task: gossip + is_bonus: true + score: 300 + - task: smartsched + is_bonus: true + score: 200 + watch: + - distbuild/pkg/scheduler + - task: wasm + is_bonus: true + score: 300 + - task: firegod + is_bonus: true + score: 200 + - task: excelwriter + is_bonus: true + score: 200 + - task: rsem + is_bonus: true + score: 200 + - task: psycher + is_bonus: true + score: 200 diff --git a/.private b/.private index b1226e2..4250668 100644 --- a/.private +++ b/.private @@ -1 +1,2 @@ -wasm/flappygopher/main_solution.go \ No newline at end of file +wasm/flappygopher/main_solution.go +rsem/try_lock.lua diff --git a/.releaser-ci.yml b/.releaser-ci.yml index 0bfd193..fcf651b 100644 --- a/.releaser-ci.yml +++ b/.releaser-ci.yml @@ -1,11 +1,5 @@ check: - image: cr.yandex/crp9onavos88ug32d5r2/grader/go-build - variables: - DOCKER_HOST: tcp://docker:2375/ - DOCKER_TLS_CERTDIR: "" - APP_HOST: docker - # services: - #- docker:dind + image: gitlab.manytask.org:5050/go/public-2024-spring/build script: - golangci-lint run --build-tags private,solution ./... #- go test -v -tags private,solution ./... @@ -19,8 +13,8 @@ rebuild-base-image: - docker when: manual script: - - docker build -f build.docker -t cr.yandex/crp9onavos88ug32d5r2/grader/go-build . - - docker push cr.yandex/crp9onavos88ug32d5r2/grader/go-build:latest + - docker build -f build.docker -t gitlab.manytask.org:5050/go/public-2024-spring/build . + - docker push gitlab.manytask.org:5050/go/public-2024-spring/build:latest deploy: only: @@ -28,9 +22,9 @@ deploy: tags: - docker script: - - docker pull cr.yandex/crp9onavos88ug32d5r2/grader/go-build:latest - - docker build -f testenv.docker -t cr.yandex/crp9onavos88ug32d5r2/grader/go . - - docker push cr.yandex/crp9onavos88ug32d5r2/grader/go:latest + - docker pull gitlab.manytask.org:5050/go/public-2024-spring/build:latest + - docker build -f testenv.docker -t gitlab.manytask.org:5050/go/public-2024-spring . + - docker push gitlab.manytask.org:5050/go/public-2024-spring:latest build-slides: only: @@ -38,28 +32,32 @@ build-slides: tags: - docker script: - - docker build lectures -t cr.yandex/crp9onavos88ug32d5r2/go-lectures - - docker push cr.yandex/crp9onavos88ug32d5r2/go-lectures + - docker build lectures -t gitlab.manytask.org:5050/go/public-2024-spring/lectures + - docker push gitlab.manytask.org:5050/go/public-2024-spring/lectures -push-to-public: - stage: .post - image: cr.yandex/crp9onavos88ug32d5r2/grader/go +update-config: only: - master script: - - git remote rm public || true - - git remote add -f public https://svparamoshkin:${CI_PUSH_TOKEN}@gitlab.manytask.org/go/public-itmo-2023-fall - - git config --global user.email 'svparamoshkin@yandex-team.ru' - - git config --global user.name 'svparamoshkin' - - git fetch public - - git branch -D public || true - - git branch public public/master - - testtool export --push --move-to-master=false - - curl -F token=$TESTER_TOKEN http://itmo-go.manytask.org/api/sync_task_columns + - > + curl -v --fail --silent -X POST \ + -H "Authorization: Bearer $TESTER_TOKEN" \ + -H "Content-type: application/x-yaml" \ + --data-binary "@.manytask.yml" \ + https://go.manytask.org/api/update_config + - > + curl -v --fail --silent -X POST \ + -H "Authorization: Bearer $TESTER_TOKEN" \ + https://go.manytask.org/api/update_cache -push-to-github: +push-to-public: stage: .post - image: cr.yandex/crp9onavos88ug32d5r2/grader/go + image: gitlab.manytask.org:5050/go/public-2024-spring + parallel: + matrix: + - REMOTE: + - git@github.com:slon/shad-go.git + - git@gitlab.manytask.org:go/public-2024-spring.git only: - master script: @@ -69,7 +67,7 @@ push-to-github: - git branch -D main || true - git checkout -b main - git remote rm github || true - - env GIT_SSH_COMMAND="ssh -i ${PWD}/private.key -o StrictHostKeyChecking=no" git remote add -f github git@github.com:slon/shad-go.git + - env GIT_SSH_COMMAND="ssh -i ${PWD}/private.key -o StrictHostKeyChecking=no" git remote add -f github $REMOTE - env GIT_SSH_COMMAND="ssh -i ${PWD}/private.key -o StrictHostKeyChecking=no" git push github main deploy-slides: @@ -79,5 +77,5 @@ deploy-slides: tags: - web script: - - docker pull cr.yandex/crp9onavos88ug32d5r2/go-lectures + - docker pull gitlab.manytask.org:5050/go/public-2024-spring/lectures - cd /srv/manytask/go && docker compose up -d diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7c47cb4..edc17f8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,26 +1,28 @@ # Как послать патч -Если вы нашли недоработку в тестах или неточность/опечатку в условии, то вы можете послать MR +Если вы нашли недоработку в тестах или неточность/опечатку в условии, то вы можете послать PR с исправлением в репозиторий курса. -За все исправления начисляются дополнительные баллы в колонке bugs в таблице. +За все исправления начисляются дополнительные баллы в колонке bonus в таблице. Размер дополнительных баллов зависит от серьёзности исправления и определяется преподавателями. ## Небольшие исправления -Небольшие исправления на <10 строк проще всего послать через веб интерфейс гитлаба. +Небольшие исправления на <10 строк проще всего послать через веб интерфейс гитхаба. -1. Откройте нужный файл в веб интерфейсе репозитория https://gitlab.com/manytask/itmo-go/public -2. Нажмите на кнопку "Edit". Во всплывающей подсказке нажмите кнопку "Fork". - ![](docs/edit-and-fork.png) -3. Внесите изменения в файл. Нажмите "Commit Changes" внизу страницы. -4. Добавьте описание вашего изменения. Нажмите "Submit Merge Request". +1. Откройте нужный файл в веб интерфейсе репозитория https://github.com/slon/shad-go +2. Нажмите на кнопку "Edit in place". + ![](docs/edit-in-place.png) +3. На следующем экране нажмите "Fork this repository". +3. Внесите изменения в файл. Нажмите "Commit Changes" сверху страницы. +4. Добавьте описание вашего изменения. Нажмите "Propose changed". +5. Нажмите "Create pull request". ## Продвинутые исправления Для многофайловых исправлений можно сначала сделать исправление локально: -1. Создайте форк https://gitlab.com/manytask/itmo-go/public аналогично тому, что выше. +1. Создайте форк https://github.com/slon/shad-go аналогично тому, что выше. 2. Закоммитьте все локальные изменения, которые вы не хотите добавлять в репозиторий курса. @@ -30,16 +32,13 @@ git checkout origin/master -b newbranchforupdate ``` -4. Внесите локальные изменения и запушьте их в свой форк на [gitlab.com](https://gitlab.com/) (не в `student`), например +4. Внесите локальные изменения и запушьте их в свой форк на [github.com](https://github.com/) (не в `student`), например ``` git add . git commit -m "Update tests" - git push https://gitlab.com/%USERNAME%/shad-go/ + git push https://github.com/%USERNAME%/shad-go/ ``` -5. В своём форке выберите созданную ветку и создайте Merge Request в репозиторий курса. Обычно GitLab подсказывает недавно запушенную ветку и предлагает создать для неё MR. +5. В своём форке выберите созданную ветку и создайте Pull Request в репозиторий курса. Обычно Github подсказывает недавно запушенную ветку и предлагает создать для неё PR. -![](docs/create-mr.png) - - На странице c формой нового Merge Request убедитесь, что ветвь назначения — `slon/shad-go:master`. Нажмите кнопку "Create Merge Request". -![](docs/create-mr-form.png) + На странице c формой нового Pull Request убедитесь, что ветвь назначения — `slon/shad-go:master`. Нажмите кнопку "Create Pull Request". diff --git a/README.md b/README.md index 4073448..ccc43f5 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,5 @@ # Курс по Го в ШАД -Для работы с кодом нужен go 1.18 или выше. - -```sh -git clone https://gitlab.com/manytask/itmo-go/public.git -cd shad-go -go test ./sum/... -``` - Проект можно открыть в любой go IDE с поддержкой модулей. ## Информация diff --git a/allocs/README.md b/allocs/README.md index 2b5b721..4ddcd88 100644 --- a/allocs/README.md +++ b/allocs/README.md @@ -15,7 +15,7 @@ ``` goos: linux goarch: amd64 -pkg: gitlab.com/manytask/itmo-go/public/allocs +pkg: gitlab.com/slon/shad-go/allocs Benchmark/count-4 73200 16294 ns/op 880 B/op 5 allocs/op Benchmark/main-4 40485 30113 ns/op 1034 B/op 9 allocs/op ``` @@ -23,7 +23,7 @@ Benchmark/main-4 40485 30113 ns/op 1034 Значения бенчмарков для авторского решения: ```goos: linux goarch: amd64 - pkg: gitlab.com/manytask/itmo-go/public/allocs + pkg: gitlab.com/slon/shad-go/allocs Benchmark/count-4 212850 5471 ns/op 4144 B/op 2 allocs/op Benchmark/main-4 143937 8247 ns/op 4176 B/op 3 allocs/op ``` diff --git a/allocs/baseline.go b/allocs/baseline.go index 9519382..cbe95bd 100644 --- a/allocs/baseline.go +++ b/allocs/baseline.go @@ -5,7 +5,6 @@ package allocs import ( "fmt" "io" - "io/ioutil" "sort" "strings" ) @@ -24,7 +23,7 @@ func NewBaselineCounter() Counter { } func (c BaselineCounter) Count(r io.Reader) error { - data, err := ioutil.ReadAll(r) + data, err := io.ReadAll(r) if err != nil { return err } diff --git a/batcher/batcher.go b/batcher/batcher.go index 38c7549..84440cb 100644 --- a/batcher/batcher.go +++ b/batcher/batcher.go @@ -2,9 +2,10 @@ package batcher -import "gitlab.com/manytask/itmo-go/public/batcher/slow" +import "gitlab.com/slon/shad-go/batcher/slow" -type Batcher struct{} +type Batcher struct { +} func NewBatcher(v *slow.Value) *Batcher { return nil diff --git a/batcher/batcher_test.go b/batcher/batcher_test.go index 3251492..6fe45a5 100644 --- a/batcher/batcher_test.go +++ b/batcher/batcher_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/goleak" - "gitlab.com/manytask/itmo-go/public/batcher/slow" + "gitlab.com/slon/shad-go/batcher/slow" ) func TestSimple(t *testing.T) { diff --git a/blowfish/blowfish_test.go b/blowfish/blowfish_test.go index 6c544d7..9936afd 100644 --- a/blowfish/blowfish_test.go +++ b/blowfish/blowfish_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" - "gitlab.com/manytask/itmo-go/public/blowfish" + "gitlab.com/slon/shad-go/blowfish" ) var _ cipher.Block = (*blowfish.Blowfish)(nil) diff --git a/build.docker b/build.docker index 03832db..e67c769 100644 --- a/build.docker +++ b/build.docker @@ -1,4 +1,4 @@ -FROM golang:1.20 +FROM golang:1.22 # enable backports for git-filter-repo RUN echo "deb http://deb.debian.org/debian bullseye-backports main" >> /etc/apt/sources.list.d/backports.list @@ -7,4 +7,4 @@ RUN apt-get update && apt-get install -y \ rsync libssl-dev postgresql sudo redis-server git-filter-repo/bullseye-backports \ && rm -rf /var/lib/apt/lists/* -RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.51.1 +RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.56.2 diff --git a/ciletters/README.md b/ciletters/README.md index c55d21f..0ea4247 100644 --- a/ciletters/README.md +++ b/ciletters/README.md @@ -35,7 +35,7 @@ Your pipeline #194613 has failed! // 194613 -- это ID pipeline'а // Далее идут последние 10 строк лога gitlab runner'а testtool: copying go.mod, go.sum and .golangci.yml testtool: running tests - testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/manytask/itmo-go/public/sum + testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/slon/shad-go/sum --- FAIL: TestSum (0.00s) sum_test.go:19: 2 + 2 == 0 != 4 sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808 diff --git a/ciletters/letter_test.go b/ciletters/letter_test.go index 43d7c12..b77b669 100644 --- a/ciletters/letter_test.go +++ b/ciletters/letter_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" - "gitlab.com/manytask/itmo-go/public/tools/testtool" + "gitlab.com/slon/shad-go/tools/testtool" ) type testCase struct { @@ -93,7 +93,7 @@ testtool: copying !change files testtool: copying testdata directory testtool: copying go.mod, go.sum and .golangci.yml testtool: running tests -testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/manytask/itmo-go/public/sum +testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/slon/shad-go/sum --- FAIL: TestSum (0.00s) sum_test.go:19: 2 + 2 == 0 != 4 sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808 @@ -113,7 +113,7 @@ ERROR: Job failed: exit code 1`, Stage: test, Job grade testtool: copying go.mod, go.sum and .golangci.yml testtool: running tests - testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/manytask/itmo-go/public/sum + testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/slon/shad-go/sum --- FAIL: TestSum (0.00s) sum_test.go:19: 2 + 2 == 0 != 4 sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808 @@ -156,7 +156,7 @@ testtool: copying !change files testtool: copying testdata directory testtool: copying go.mod, go.sum and .golangci.yml testtool: running tests -testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/manytask/itmo-go/public/sum +testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/slon/shad-go/sum --- FAIL: TestSum (0.00s) sum_test.go:19: 2 + 2 == 0 != 4 sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808 @@ -188,7 +188,7 @@ ERROR: Job failed: exit code 1`, Stage: %v, Job %v testtool: copying go.mod, go.sum and .golangci.yml testtool: running tests - testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/manytask/itmo-go/public/sum + testtool: > go test -mod readonly -tags private -c -o /tmp/bincache730817117/5d83984f885e61c1 gitlab.com/slon/shad-go/sum --- FAIL: TestSum (0.00s) sum_test.go:19: 2 + 2 == 0 != 4 sum_test.go:19: 9223372036854775807 + 1 == 0 != -9223372036854775808 diff --git a/cond/cond_test.go b/cond/cond_test.go index cee02e6..99a503c 100644 --- a/cond/cond_test.go +++ b/cond/cond_test.go @@ -1,6 +1,7 @@ package cond import ( + "gitlab.com/slon/shad-go/tools/testtool" "sync" "testing" "time" @@ -44,6 +45,38 @@ func TestCondSignal(t *testing.T) { c.Signal() } +func TestCondSignalOveruse(t *testing.T) { + var m sync.Mutex + c := New(&m) + running := make(chan bool, 1) + awake := make(chan bool, 1) + + for i := 0; i < 5; i++ { + c.Signal() // Checks if empty signals are not deadlocking + } + + go func() { + m.Lock() + running <- true + c.Wait() // Checks if it will wait after empty signals + awake <- true + m.Unlock() + + }() + + <-running + + select { + case <-awake: + t.Fatal("goroutine not asleep") + default: + } + m.Lock() + c.Signal() + m.Unlock() + <-awake // Will deadlock if no goroutine wakes up +} + func TestCondSignalGenerations(t *testing.T) { var m sync.Mutex c := New(&m) @@ -182,3 +215,7 @@ func TestCondSignalStealing(t *testing.T) { cond.Broadcast() } } + +func TestNoSyncPackageImported(t *testing.T) { + testtool.CheckForbiddenImport(t, "sync") +} diff --git a/consistenthash/hash_test.go b/consistenthash/hash_test.go index aa17a7d..7c4f02c 100644 --- a/consistenthash/hash_test.go +++ b/consistenthash/hash_test.go @@ -57,7 +57,7 @@ func TestHash_EvenDistribution(t *testing.T) { h.AddNode(&n) } - counts := map[*node]int{} + counts := map[*node]float64{} const N = 1 << 16 for i := 0; i < N; i++ { counts[h.GetNode(fmt.Sprintf("key%d", i))] += 1 @@ -65,14 +65,23 @@ func TestHash_EvenDistribution(t *testing.T) { const P = 1 / float64(K) const variance = N * (P) * (1 - P) - stddev := math.Sqrt(variance) - t.Logf("P = %v, var = %v, stddev = %v", P, variance, stddev) + idealStddev := math.Sqrt(variance) + + t.Logf("P = %v, var = %v, stddev = %v", P, variance, idealStddev) t.Logf("counts = %v", maps.Values(counts)) + total := float64(N) + mean := total / K + + var dispersion float64 for _, count := range counts { - require.Greater(t, count, int(N/K-stddev*10)) - require.Less(t, count, int(N/K+stddev*10)) + dispersion += (count - mean) * (count - mean) } + + realStddev := math.Sqrt(dispersion / K) + t.Logf("read stddev = %v", realStddev) + + require.Less(t, math.Abs(realStddev-idealStddev)/idealStddev, float64(4)) } func TestHash_ConsistentDistribution(t *testing.T) { diff --git a/coverme/app/app.go b/coverme/app/app.go index e4dc905..4deb8ad 100644 --- a/coverme/app/app.go +++ b/coverme/app/app.go @@ -12,8 +12,8 @@ import ( "github.com/gorilla/handlers" "github.com/gorilla/mux" - "gitlab.com/manytask/itmo-go/public/coverme/models" - "gitlab.com/manytask/itmo-go/public/coverme/utils" + "gitlab.com/slon/shad-go/coverme/models" + "gitlab.com/slon/shad-go/coverme/utils" ) type App struct { diff --git a/coverme/client/client.go b/coverme/client/client.go index 9d8d92f..93df2f9 100644 --- a/coverme/client/client.go +++ b/coverme/client/client.go @@ -8,7 +8,7 @@ import ( "fmt" "net/http" - "gitlab.com/manytask/itmo-go/public/coverme/models" + "gitlab.com/slon/shad-go/coverme/models" ) type Client struct { diff --git a/coverme/main.go b/coverme/main.go index 6e07230..25262af 100644 --- a/coverme/main.go +++ b/coverme/main.go @@ -5,8 +5,8 @@ package main import ( "flag" - "gitlab.com/manytask/itmo-go/public/coverme/app" - "gitlab.com/manytask/itmo-go/public/coverme/models" + "gitlab.com/slon/shad-go/coverme/app" + "gitlab.com/slon/shad-go/coverme/models" ) func main() { diff --git a/dao/README.md b/dao/README.md index f3f7500..bf637fb 100644 --- a/dao/README.md +++ b/dao/README.md @@ -31,18 +31,14 @@ sudo apt install postgresql Альтернативный способ — запустить бд в докере. Для этого нужно установить docker и docker-compose по инструкции из [dockertest](../dockertest/README.md). -Добиться успешного запуска -``` -go test -v ./dockertest/... -``` Запускать тесты можно будет так: ``` -(cd dao && docker-compose up -d && sleep 1 && env PGCONN="host=127.0.0.1 port=5432 database=shad-go user=gopher password=pass" go test -v ./... -count=1 || true && docker-compose down) +(cd dao && docker compose up -d --wait && env PGCONN="host=127.0.0.1 port=5432 database=shad-go user=gopher password=pass" go test -v ./... -count=1 || true && docker compose down) ``` Эта команда стартует docker с postgresql, запускает тесты, передав им DSN через переменную окружения, удаляет контейнеры в конце. Как подчистить контейнеры, если что-то пошло не так: ``` -(cd dao && docker-compose down) +(cd dao && docker compose down) ``` diff --git a/dao/dao_test.go b/dao/dao_test.go index 1a76ac0..63a39ef 100644 --- a/dao/dao_test.go +++ b/dao/dao_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/goleak" - "gitlab.com/manytask/itmo-go/public/pgfixture" + "gitlab.com/slon/shad-go/pgfixture" ) func TestDao(t *testing.T) { @@ -36,7 +36,7 @@ func TestDao(t *testing.T) { alice, err := dao.Lookup(ctx, aliceID) require.NoError(t, err) - require.Equal(t, alice, User{ID: aliceID, Name: "Alice"}) + require.Equal(t, User{ID: aliceID, Name: "Alice"}, alice) require.NoError(t, dao.Delete(ctx, bobID)) @@ -44,6 +44,7 @@ func TestDao(t *testing.T) { require.ErrorIs(t, err, sql.ErrNoRows) require.NoError(t, dao.Update(ctx, &User{ID: charlieID, Name: "Chaplin"})) + require.Error(t, dao.Update(ctx, &User{ID: 999, Name: "FooBar"})) users, err := dao.List(ctx) require.NoError(t, err) diff --git a/dao/docker-compose.yaml b/dao/docker-compose.yaml index 0bc4782..1358bcf 100644 --- a/dao/docker-compose.yaml +++ b/dao/docker-compose.yaml @@ -8,3 +8,8 @@ services: POSTGRES_PASSWORD: pass ports: - 5432:5432 + healthcheck: + test: [ "CMD-SHELL", "pg_isready -U $${POSTGRES_USER}" ] + interval: 1s + timeout: 3s + retries: 5 diff --git a/digitalclock/main_test.go b/digitalclock/main_test.go index 4862399..91a32c2 100644 --- a/digitalclock/main_test.go +++ b/digitalclock/main_test.go @@ -5,7 +5,6 @@ import ( "fmt" "image" "image/png" - "io/ioutil" "net/http" "net/url" "os" @@ -18,10 +17,10 @@ import ( "github.com/stretchr/testify/require" - "gitlab.com/manytask/itmo-go/public/tools/testtool" + "gitlab.com/slon/shad-go/tools/testtool" ) -const importPath = "gitlab.com/manytask/itmo-go/public/digitalclock" +const importPath = "gitlab.com/slon/shad-go/digitalclock" var binCache testtool.BinCache @@ -125,7 +124,7 @@ func TestDigitalClock_valid(t *testing.T) { port, stop := startServer(t) defer stop() - files, err := ioutil.ReadDir("./testdata") + files, err := os.ReadDir("./testdata") require.NoError(t, err) c := &http.Client{Timeout: time.Second * 10} diff --git a/distbuild/disttest/fixture.go b/distbuild/disttest/fixture.go index ad2d76c..ff31b2b 100644 --- a/distbuild/disttest/fixture.go +++ b/distbuild/disttest/fixture.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "io/ioutil" "net" "net/http" "net/url" @@ -17,13 +16,13 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/goleak" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/api" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/artifact" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/client" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/dist" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/filecache" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/worker" - "gitlab.com/manytask/itmo-go/public/tools/testtool" + "gitlab.com/slon/shad-go/distbuild/pkg/api" + "gitlab.com/slon/shad-go/distbuild/pkg/artifact" + "gitlab.com/slon/shad-go/distbuild/pkg/client" + "gitlab.com/slon/shad-go/distbuild/pkg/dist" + "gitlab.com/slon/shad-go/distbuild/pkg/filecache" + "gitlab.com/slon/shad-go/distbuild/pkg/worker" + "gitlab.com/slon/shad-go/tools/testtool" "go.uber.org/zap" ) @@ -50,7 +49,11 @@ type Config struct { WorkerCount int } -func newEnv(t *testing.T, config *Config) (e *env, cancel func()) { +func newEnv(t *testing.T, config *Config) (e *env) { + t.Cleanup(func() { + goleak.VerifyNone(t) + }) + cwd, err := os.Getwd() require.NoError(t, err) @@ -60,9 +63,9 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) { rootDir := filepath.Join(absCWD, "workdir", t.Name()) require.NoError(t, os.RemoveAll(rootDir)) - if err = os.MkdirAll(rootDir, 0o777); err != nil { + if err = os.MkdirAll(rootDir, 0777); err != nil { if errors.Is(err, os.ErrPermission) { - rootDir, err = ioutil.TempDir("", "") + rootDir, err = os.MkdirTemp("", "") require.NoError(t, err) } else { require.NoError(t, err) @@ -90,6 +93,10 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) { env.Logger, err = cfg.Build() require.NoError(t, err) + t.Cleanup(func() { + _ = env.Logger.Sync() + }) + t.Helper() t.Logf("test is running inside %s; see test.log file for more info", filepath.Join("workdir", t.Name())) @@ -100,6 +107,7 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) { var cancelRootContext func() env.Ctx, cancelRootContext = context.WithCancel(context.Background()) + t.Cleanup(cancelRootContext) env.Client = client.NewClient( env.Logger.Named("client"), @@ -113,6 +121,7 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) { env.Logger.Named("coordinator"), coordinatorCache, ) + t.Cleanup(env.Coordinator.Stop) router := http.NewServeMux() router.Handle("/coordinator/", http.StripPrefix("/coordinator", env.Coordinator)) @@ -161,6 +170,11 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) { } }() + t.Cleanup(func() { + cancelRootContext() + _ = env.HTTP.Shutdown(context.Background()) + }) + for _, w := range env.Workers { go func(w *worker.Worker) { err := w.Run(env.Ctx) @@ -181,20 +195,14 @@ func newEnv(t *testing.T, config *Config) (e *env, cancel func()) { } }() - return env, func() { - cancelRootContext() - _ = env.HTTP.Shutdown(context.Background()) - _ = env.Logger.Sync() - - goleak.VerifyNone(t) - } + return env } func newWinFileSink(u *url.URL) (zap.Sink, error) { if len(u.Opaque) > 0 { // Remove leading slash left by url.Parse() - return os.OpenFile(u.Opaque[1:], os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o644) + return os.OpenFile(u.Opaque[1:], os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) } // if url.URL is empty, don't panic slice index error - return os.OpenFile(u.Opaque, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o644) + return os.OpenFile(u.Opaque, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) } diff --git a/distbuild/disttest/recorder.go b/distbuild/disttest/recorder.go index 2a5d32a..3bef98d 100644 --- a/distbuild/disttest/recorder.go +++ b/distbuild/disttest/recorder.go @@ -1,7 +1,7 @@ package disttest import ( - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) type JobResult struct { diff --git a/distbuild/disttest/single_worker_test.go b/distbuild/disttest/single_worker_test.go index 6291aa9..1d4fdd6 100644 --- a/distbuild/disttest/single_worker_test.go +++ b/distbuild/disttest/single_worker_test.go @@ -2,13 +2,14 @@ package disttest import ( "fmt" - "io/ioutil" + "io" + "os" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) var singleWorkerConfig = &Config{WorkerCount: 1} @@ -26,8 +27,7 @@ var echoGraph = build.Graph{ } func TestSingleCommand(t *testing.T) { - env, cancel := newEnv(t, singleWorkerConfig) - defer cancel() + env := newEnv(t, singleWorkerConfig) recorder := NewRecorder() require.NoError(t, env.Client.Build(env.Ctx, echoGraph, recorder)) @@ -37,10 +37,9 @@ func TestSingleCommand(t *testing.T) { } func TestJobCaching(t *testing.T) { - env, cancel := newEnv(t, singleWorkerConfig) - defer cancel() + env := newEnv(t, singleWorkerConfig) - tmpFile, err := ioutil.TempFile("", "") + tmpFile, err := os.CreateTemp("", "") require.NoError(t, err) graph := build.Graph{ @@ -62,12 +61,12 @@ func TestJobCaching(t *testing.T) { assert.Len(t, recorder.Jobs, 1) assert.Equal(t, &JobResult{Stdout: "OK\n", Code: new(int)}, recorder.Jobs[build.ID{'a'}]) - require.NoError(t, ioutil.WriteFile(tmpFile.Name(), []byte("NOTOK\n"), 0o666)) + require.NoError(t, os.WriteFile(tmpFile.Name(), []byte("NOTOK\n"), 0666)) // Second build must get results from cache. require.NoError(t, env.Client.Build(env.Ctx, graph, NewRecorder())) - output, err := ioutil.ReadAll(tmpFile) + output, err := io.ReadAll(tmpFile) require.NoError(t, err) require.Equal(t, []byte("NOTOK\n"), output) } @@ -94,8 +93,7 @@ var sourceFilesGraph = build.Graph{ } func TestSourceFiles(t *testing.T) { - env, cancel := newEnv(t, singleWorkerConfig) - defer cancel() + env := newEnv(t, singleWorkerConfig) recorder := NewRecorder() require.NoError(t, env.Client.Build(env.Ctx, sourceFilesGraph, recorder)) @@ -125,8 +123,7 @@ var artifactTransferGraph = build.Graph{ } func TestArtifactTransferBetweenJobs(t *testing.T) { - env, cancel := newEnv(t, singleWorkerConfig) - defer cancel() + env := newEnv(t, singleWorkerConfig) recorder := NewRecorder() require.NoError(t, env.Client.Build(env.Ctx, artifactTransferGraph, recorder)) diff --git a/distbuild/disttest/three_workers_test.go b/distbuild/disttest/three_workers_test.go index 14cf40d..ecef8ae 100644 --- a/distbuild/disttest/three_workers_test.go +++ b/distbuild/disttest/three_workers_test.go @@ -9,14 +9,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) var threeWorkerConfig = &Config{WorkerCount: 3} func TestArtifactTransferBetweenWorkers(t *testing.T) { - env, cancel := newEnv(t, threeWorkerConfig) - defer cancel() + env := newEnv(t, threeWorkerConfig) baseJob := build.Job{ ID: build.ID{'a'}, diff --git a/distbuild/pkg/api/build.go b/distbuild/pkg/api/build.go index e9faf2d..56e4924 100644 --- a/distbuild/pkg/api/build.go +++ b/distbuild/pkg/api/build.go @@ -3,7 +3,7 @@ package api import ( "context" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) type BuildRequest struct { @@ -25,7 +25,8 @@ type BuildFailed struct { Error string } -type BuildFinished struct{} +type BuildFinished struct { +} type UploadDone struct{} @@ -33,7 +34,8 @@ type SignalRequest struct { UploadDone *UploadDone } -type SignalResponse struct{} +type SignalResponse struct { +} type StatusWriter interface { Started(rsp *BuildStarted) error diff --git a/distbuild/pkg/api/build_client.go b/distbuild/pkg/api/build_client.go index 767256f..dbd42ae 100644 --- a/distbuild/pkg/api/build_client.go +++ b/distbuild/pkg/api/build_client.go @@ -7,10 +7,11 @@ import ( "go.uber.org/zap" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) -type BuildClient struct{} +type BuildClient struct { +} func NewBuildClient(l *zap.Logger, endpoint string) *BuildClient { panic("implement me") diff --git a/distbuild/pkg/api/build_test.go b/distbuild/pkg/api/build_test.go index 26272aa..b2bcd78 100644 --- a/distbuild/pkg/api/build_test.go +++ b/distbuild/pkg/api/build_test.go @@ -12,9 +12,9 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/api" - mock "gitlab.com/manytask/itmo-go/public/distbuild/pkg/api/mock" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/api" + mock "gitlab.com/slon/shad-go/distbuild/pkg/api/mock" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) //go:generate mockgen -package mock -destination mock/mock.go . Service @@ -28,7 +28,6 @@ type env struct { func (e *env) stop() { e.server.Close() - e.ctrl.Finish() } func newEnv(t *testing.T) (*env, func()) { @@ -56,8 +55,8 @@ func TestBuildSignal(t *testing.T) { ctx := context.Background() - buildIDa := build.ID{0o1} - buildIDb := build.ID{0o2} + buildIDa := build.ID{01} + buildIDb := build.ID{02} req := &api.SignalRequest{} rsp := &api.SignalResponse{} @@ -91,10 +90,10 @@ func TestBuildRunning(t *testing.T) { ctx := context.Background() - buildID := build.ID{0o2} + buildID := build.ID{02} req := &api.BuildRequest{ - Graph: build.Graph{SourceFiles: map[build.ID]string{{0o1}: "a.txt"}}, + Graph: build.Graph{SourceFiles: map[build.ID]string{{01}: "a.txt"}}, } started := &api.BuildStarted{ID: buildID} @@ -141,7 +140,7 @@ func TestBuildResultsStreaming(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - buildID := build.ID{0o2} + buildID := build.ID{02} req := &api.BuildRequest{} started := &api.BuildStarted{ID: buildID} diff --git a/distbuild/pkg/api/heartbeat.go b/distbuild/pkg/api/heartbeat.go index 7e7116a..d97f2a1 100644 --- a/distbuild/pkg/api/heartbeat.go +++ b/distbuild/pkg/api/heartbeat.go @@ -3,7 +3,7 @@ package api import ( "context" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) // JobResult описывает результат работы джоба. diff --git a/distbuild/pkg/api/heartbeat_test.go b/distbuild/pkg/api/heartbeat_test.go index 60f8311..eaad7f5 100644 --- a/distbuild/pkg/api/heartbeat_test.go +++ b/distbuild/pkg/api/heartbeat_test.go @@ -11,16 +11,15 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/api" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/api/mock" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/api" + "gitlab.com/slon/shad-go/distbuild/pkg/api/mock" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) //go:generate mockgen -package mock -destination mock/heartbeat.go . HeartbeatService func TestHeartbeat(t *testing.T) { ctrl := gomock.NewController(t) - defer ctrl.Finish() l := zaptest.NewLogger(t) m := mock.NewMockHeartbeatService(ctrl) diff --git a/distbuild/pkg/api/mock/heartbeat.go b/distbuild/pkg/api/mock/heartbeat.go index 0134e3b..e8dc165 100644 --- a/distbuild/pkg/api/mock/heartbeat.go +++ b/distbuild/pkg/api/mock/heartbeat.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: gitlab.com/manytask/itmo-go/public/distbuild/pkg/api (interfaces: HeartbeatService) +// Source: gitlab.com/slon/shad-go/distbuild/pkg/api (interfaces: HeartbeatService) // Package mock is a generated GoMock package. package mock @@ -7,7 +7,7 @@ package mock import ( context "context" gomock "github.com/golang/mock/gomock" - api "gitlab.com/manytask/itmo-go/public/distbuild/pkg/api" + api "gitlab.com/slon/shad-go/distbuild/pkg/api" reflect "reflect" ) diff --git a/distbuild/pkg/api/mock/mock.go b/distbuild/pkg/api/mock/mock.go index 02e2887..05c31d8 100644 --- a/distbuild/pkg/api/mock/mock.go +++ b/distbuild/pkg/api/mock/mock.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: gitlab.com/manytask/itmo-go/public/distbuild/pkg/api (interfaces: Service) +// Source: gitlab.com/slon/shad-go/distbuild/pkg/api (interfaces: Service) // Package mock is a generated GoMock package. package mock @@ -7,8 +7,8 @@ package mock import ( context "context" gomock "github.com/golang/mock/gomock" - api "gitlab.com/manytask/itmo-go/public/distbuild/pkg/api" - build "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + api "gitlab.com/slon/shad-go/distbuild/pkg/api" + build "gitlab.com/slon/shad-go/distbuild/pkg/build" reflect "reflect" ) diff --git a/distbuild/pkg/artifact/cache.go b/distbuild/pkg/artifact/cache.go index 0a28732..269fb74 100644 --- a/distbuild/pkg/artifact/cache.go +++ b/distbuild/pkg/artifact/cache.go @@ -4,12 +4,11 @@ import ( "encoding/hex" "errors" "fmt" - "io/ioutil" "os" "path/filepath" "sync" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) var ( @@ -34,18 +33,18 @@ func NewCache(root string) (*Cache, error) { if err := os.RemoveAll(tmpDir); err != nil { return nil, err } - if err := os.MkdirAll(tmpDir, 0o777); err != nil { + if err := os.MkdirAll(tmpDir, 0777); err != nil { return nil, err } cacheDir := filepath.Join(root, "c") - if err := os.MkdirAll(cacheDir, 0o777); err != nil { + if err := os.MkdirAll(cacheDir, 0777); err != nil { return nil, err } for i := 0; i < 256; i++ { d := hex.EncodeToString([]byte{uint8(i)}) - if err := os.MkdirAll(filepath.Join(cacheDir, d), 0o777); err != nil { + if err := os.MkdirAll(filepath.Join(cacheDir, d), 0777); err != nil { return nil, err } } @@ -110,13 +109,13 @@ func (c *Cache) writeUnlock(id build.ID) { } func (c *Cache) Range(artifactFn func(artifact build.ID) error) error { - shards, err := ioutil.ReadDir(c.cacheDir) + shards, err := os.ReadDir(c.cacheDir) if err != nil { return err } for _, shard := range shards { - dirs, err := ioutil.ReadDir(filepath.Join(c.cacheDir, shard.Name())) + dirs, err := os.ReadDir(filepath.Join(c.cacheDir, shard.Name())) if err != nil { return err } @@ -151,7 +150,7 @@ func (c *Cache) Create(artifact build.ID) (path string, commit, abort func() err } path = filepath.Join(c.tmpDir, artifact.String()) - if err = os.MkdirAll(path, 0o777); err != nil { + if err = os.MkdirAll(path, 0777); err != nil { c.writeUnlock(artifact) return } diff --git a/distbuild/pkg/artifact/cache_test.go b/distbuild/pkg/artifact/cache_test.go index e2b5581..c0e1d38 100644 --- a/distbuild/pkg/artifact/cache_test.go +++ b/distbuild/pkg/artifact/cache_test.go @@ -2,15 +2,14 @@ package artifact_test import ( "errors" - "io/ioutil" "os" "path/filepath" "testing" "github.com/stretchr/testify/require" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/artifact" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/artifact" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) type testCache struct { @@ -23,7 +22,7 @@ func (c *testCache) cleanup() { } func newTestCache(t *testing.T) *testCache { - tmpDir, err := ioutil.TempDir("", "") + tmpDir, err := os.MkdirTemp("", "") require.NoError(t, err) cache, err := artifact.NewCache(tmpDir) diff --git a/distbuild/pkg/artifact/client.go b/distbuild/pkg/artifact/client.go index cc39835..2ae9e9d 100644 --- a/distbuild/pkg/artifact/client.go +++ b/distbuild/pkg/artifact/client.go @@ -5,7 +5,7 @@ package artifact import ( "context" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) // Download artifact from remote cache into local cache. diff --git a/distbuild/pkg/artifact/client_test.go b/distbuild/pkg/artifact/client_test.go index 99df4a0..7e959c0 100644 --- a/distbuild/pkg/artifact/client_test.go +++ b/distbuild/pkg/artifact/client_test.go @@ -2,17 +2,17 @@ package artifact_test import ( "context" - "io/ioutil" "net/http" "net/http/httptest" + "os" "path/filepath" "testing" "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/artifact" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/artifact" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) func TestArtifactTransfer(t *testing.T) { @@ -23,7 +23,7 @@ func TestArtifactTransfer(t *testing.T) { dir, commit, _, err := remoteCache.Create(id) require.NoError(t, err) - require.NoError(t, ioutil.WriteFile(filepath.Join(dir, "a.txt"), []byte("foobar"), 0o777)) + require.NoError(t, os.WriteFile(filepath.Join(dir, "a.txt"), []byte("foobar"), 0777)) require.NoError(t, commit()) l := zaptest.NewLogger(t) @@ -42,7 +42,7 @@ func TestArtifactTransfer(t *testing.T) { require.NoError(t, err) defer unlock() - content, err := ioutil.ReadFile(filepath.Join(dir, "a.txt")) + content, err := os.ReadFile(filepath.Join(dir, "a.txt")) require.NoError(t, err) require.Equal(t, []byte("foobar"), content) diff --git a/distbuild/pkg/build/graph.go b/distbuild/pkg/build/graph.go index 28df722..7e8946a 100644 --- a/distbuild/pkg/build/graph.go +++ b/distbuild/pkg/build/graph.go @@ -39,7 +39,7 @@ type Job struct { // exec - выполняет произвольную команду // cat - записывает строку в файл // -// Все строки в описании команды могут содержать в себе на переменные. Перед выполнением +// Все строки в описании команды могут содержать в себе ссылки на контекстные переменные. Перед выполнением // реальной команды, переменные заменяются на их реальные значения. // // {{.OutputDir}} - абсолютный путь до выходной директории джоба. diff --git a/distbuild/pkg/client/build.go b/distbuild/pkg/client/build.go index 744581f..8d018e1 100644 --- a/distbuild/pkg/client/build.go +++ b/distbuild/pkg/client/build.go @@ -7,10 +7,11 @@ import ( "go.uber.org/zap" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) -type Client struct{} +type Client struct { +} func NewClient( l *zap.Logger, diff --git a/distbuild/pkg/dist/coordinator.go b/distbuild/pkg/dist/coordinator.go index 1e6625c..2a30dd6 100644 --- a/distbuild/pkg/dist/coordinator.go +++ b/distbuild/pkg/dist/coordinator.go @@ -8,11 +8,12 @@ import ( "go.uber.org/zap" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/filecache" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/scheduler" + "gitlab.com/slon/shad-go/distbuild/pkg/filecache" + "gitlab.com/slon/shad-go/distbuild/pkg/scheduler" ) -type Coordinator struct{} +type Coordinator struct { +} var defaultConfig = scheduler.Config{ CacheTimeout: time.Millisecond * 10, @@ -26,6 +27,8 @@ func NewCoordinator( panic("implement me") } +func (c *Coordinator) Stop() {} + func (c *Coordinator) ServeHTTP(w http.ResponseWriter, r *http.Request) { panic("implement me") } diff --git a/distbuild/pkg/filecache/client.go b/distbuild/pkg/filecache/client.go index ea8a948..2840816 100644 --- a/distbuild/pkg/filecache/client.go +++ b/distbuild/pkg/filecache/client.go @@ -7,10 +7,11 @@ import ( "go.uber.org/zap" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) -type Client struct{} +type Client struct { +} func NewClient(l *zap.Logger, endpoint string) *Client { panic("implement me") diff --git a/distbuild/pkg/filecache/client_test.go b/distbuild/pkg/filecache/client_test.go index eeba44f..db1154e 100644 --- a/distbuild/pkg/filecache/client_test.go +++ b/distbuild/pkg/filecache/client_test.go @@ -3,9 +3,9 @@ package filecache_test import ( "bytes" "context" - "io/ioutil" "net/http" "net/http/httptest" + "os" "path/filepath" "sync" "testing" @@ -14,8 +14,8 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/filecache" + "gitlab.com/slon/shad-go/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/filecache" ) type env struct { @@ -52,7 +52,7 @@ func TestFileUpload(t *testing.T) { content := bytes.Repeat([]byte("foobar"), 1024*1024) tmpFilePath := filepath.Join(env.cache.tmpDir, "foo.txt") - require.NoError(t, ioutil.WriteFile(tmpFilePath, content, 0o666)) + require.NoError(t, os.WriteFile(tmpFilePath, content, 0666)) ctx := context.Background() @@ -65,7 +65,7 @@ func TestFileUpload(t *testing.T) { require.NoError(t, err) defer unlock() - actualContent, err := ioutil.ReadFile(path) + actualContent, err := os.ReadFile(path) require.NoError(t, err) require.Equal(t, content, actualContent) }) @@ -123,7 +123,7 @@ func TestFileDownload(t *testing.T) { require.NoError(t, err) defer unlock() - content, err := ioutil.ReadFile(path) + content, err := os.ReadFile(path) require.NoError(t, err) require.Equal(t, []byte("foobar"), content) } diff --git a/distbuild/pkg/filecache/filecache.go b/distbuild/pkg/filecache/filecache.go index ee9e9ba..8f31d50 100644 --- a/distbuild/pkg/filecache/filecache.go +++ b/distbuild/pkg/filecache/filecache.go @@ -6,8 +6,8 @@ import ( "os" "path/filepath" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/artifact" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/artifact" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) var ( diff --git a/distbuild/pkg/filecache/filecache_test.go b/distbuild/pkg/filecache/filecache_test.go index fbd8676..73860bc 100644 --- a/distbuild/pkg/filecache/filecache_test.go +++ b/distbuild/pkg/filecache/filecache_test.go @@ -2,14 +2,13 @@ package filecache_test import ( "errors" - "io/ioutil" "os" "testing" "github.com/stretchr/testify/require" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/filecache" + "gitlab.com/slon/shad-go/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/filecache" ) type testCache struct { @@ -18,7 +17,7 @@ type testCache struct { } func newCache(t *testing.T) *testCache { - tmpDir, err := ioutil.TempDir("", "filecache") + tmpDir, err := os.MkdirTemp("", "filecache") require.NoError(t, err) c, err := filecache.New(tmpDir) @@ -36,25 +35,25 @@ func (c *testCache) cleanup() { func TestFileCache(t *testing.T) { cache := newCache(t) - _, abort, err := cache.Write(build.ID{0o1}) + _, abort, err := cache.Write(build.ID{01}) require.NoError(t, err) require.NoError(t, abort()) - _, _, err = cache.Get(build.ID{0o1}) + _, _, err = cache.Get(build.ID{01}) require.Truef(t, errors.Is(err, filecache.ErrNotFound), "%v", err) - f, _, err := cache.Write(build.ID{0o2}) + f, _, err := cache.Write(build.ID{02}) require.NoError(t, err) _, err = f.Write([]byte("foo bar")) require.NoError(t, err) require.NoError(t, f.Close()) - path, unlock, err := cache.Get(build.ID{0o2}) + path, unlock, err := cache.Get(build.ID{02}) require.NoError(t, err) defer unlock() - content, err := ioutil.ReadFile(path) + content, err := os.ReadFile(path) require.NoError(t, err) require.Equal(t, []byte("foo bar"), content) } diff --git a/distbuild/pkg/scheduler/scheduler.go b/distbuild/pkg/scheduler/scheduler.go index bf2cda6..da37cc5 100644 --- a/distbuild/pkg/scheduler/scheduler.go +++ b/distbuild/pkg/scheduler/scheduler.go @@ -8,8 +8,8 @@ import ( "go.uber.org/zap" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/api" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/build" + "gitlab.com/slon/shad-go/distbuild/pkg/api" + "gitlab.com/slon/shad-go/distbuild/pkg/build" ) var TimeAfter = time.After @@ -25,7 +25,8 @@ type Config struct { DepsTimeout time.Duration } -type Scheduler struct{} +type Scheduler struct { +} func NewScheduler(l *zap.Logger, config Config) *Scheduler { panic("implement me") @@ -46,3 +47,7 @@ func (c *Scheduler) ScheduleJob(job *api.JobSpec) *PendingJob { func (c *Scheduler) PickJob(ctx context.Context, workerID api.WorkerID) *PendingJob { panic("implement me") } + +func (c *Scheduler) Stop() { + panic("implement me") +} diff --git a/distbuild/pkg/tarstream/stream_test.go b/distbuild/pkg/tarstream/stream_test.go index fa81339..f970880 100644 --- a/distbuild/pkg/tarstream/stream_test.go +++ b/distbuild/pkg/tarstream/stream_test.go @@ -2,7 +2,6 @@ package tarstream_test import ( "bytes" - "io/ioutil" "os" "path/filepath" "testing" @@ -10,11 +9,11 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/sys/unix" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/tarstream" + "gitlab.com/slon/shad-go/distbuild/pkg/tarstream" ) func TestTarStream(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "tarstream") + tmpDir, err := os.MkdirTemp("", "tarstream") require.NoError(t, err) t.Logf("running inside %s", tmpDir) @@ -22,15 +21,15 @@ func TestTarStream(t *testing.T) { from := filepath.Join(tmpDir, "from") to := filepath.Join(tmpDir, "to") - require.NoError(t, os.Mkdir(from, 0o777)) - require.NoError(t, os.Mkdir(to, 0o777)) + require.NoError(t, os.Mkdir(from, 0777)) + require.NoError(t, os.Mkdir(to, 0777)) var buf bytes.Buffer - require.NoError(t, os.Mkdir(filepath.Join(from, "a"), 0o777)) - require.NoError(t, os.MkdirAll(filepath.Join(from, "b", "c", "d"), 0o777)) - require.NoError(t, ioutil.WriteFile(filepath.Join(from, "a", "x.bin"), []byte("xxx"), 0o777)) - require.NoError(t, ioutil.WriteFile(filepath.Join(from, "b", "c", "y.txt"), []byte("yyy"), 0o666)) + require.NoError(t, os.Mkdir(filepath.Join(from, "a"), 0777)) + require.NoError(t, os.MkdirAll(filepath.Join(from, "b", "c", "d"), 0777)) + require.NoError(t, os.WriteFile(filepath.Join(from, "a", "x.bin"), []byte("xxx"), 0777)) + require.NoError(t, os.WriteFile(filepath.Join(from, "b", "c", "y.txt"), []byte("yyy"), 0666)) require.NoError(t, tarstream.Send(from, &buf)) @@ -53,15 +52,15 @@ func TestTarStream(t *testing.T) { require.Equal(t, mode.String(), st.Mode().String()) - b, err := ioutil.ReadFile(path) + b, err := os.ReadFile(path) require.NoError(t, err) require.Equal(t, content, b) } - checkFile(filepath.Join(to, "a", "x.bin"), []byte("xxx"), 0o755) - checkFile(filepath.Join(to, "b", "c", "y.txt"), []byte("yyy"), 0o644) + checkFile(filepath.Join(to, "a", "x.bin"), []byte("xxx"), 0755) + checkFile(filepath.Join(to, "b", "c", "y.txt"), []byte("yyy"), 0644) } func init() { - unix.Umask(0o022) + unix.Umask(0022) } diff --git a/distbuild/pkg/worker/worker.go b/distbuild/pkg/worker/worker.go index 897c03d..af06d12 100644 --- a/distbuild/pkg/worker/worker.go +++ b/distbuild/pkg/worker/worker.go @@ -8,12 +8,13 @@ import ( "go.uber.org/zap" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/api" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/artifact" - "gitlab.com/manytask/itmo-go/public/distbuild/pkg/filecache" + "gitlab.com/slon/shad-go/distbuild/pkg/api" + "gitlab.com/slon/shad-go/distbuild/pkg/artifact" + "gitlab.com/slon/shad-go/distbuild/pkg/filecache" ) -type Worker struct{} +type Worker struct { +} func New( workerID api.WorkerID, diff --git a/docs/allocation_profiling.md b/docs/allocation_profiling.md index 2d410a6..a86d0db 100644 --- a/docs/allocation_profiling.md +++ b/docs/allocation_profiling.md @@ -7,7 +7,7 @@ ✗ go test -v -run=^$ -bench=BenchmarkSprintf -memprofile=mem.out ./varfmt/... goos: linux goarch: amd64 -pkg: gitlab.com/manytask/itmo-go/public/varfmt +pkg: gitlab.com/slon/shad-go/varfmt cpu: Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz BenchmarkSprintf BenchmarkSprintf/small @@ -17,7 +17,7 @@ BenchmarkSprintf/small_string-8 13282659 84.48 ns/op 16 B/op BenchmarkSprintf/big BenchmarkSprintf/big-8 20089 62372 ns/op 16388 B/op 1 allocs/op PASS -ok gitlab.com/manytask/itmo-go/public/varfmt 4.363s +ok gitlab.com/slon/shad-go/varfmt 4.363s ``` Сэмплы профайлера будут записаны в бинарный файл `mem.out`. @@ -53,7 +53,7 @@ Showing nodes accounting for 715.73MB, 99.37% of 720.23MB total Dropped 24 nodes (cum <= 3.60MB) flat flat% sum% cum cum% 715.73MB 99.37% 99.37% 716.73MB 99.51% fmt.Sprintf - 0 0% 99.37% 716.73MB 99.51% gitlab.com/manytask/itmo-go/public/varfmt.BenchmarkSprintf.func1 + 0 0% 99.37% 716.73MB 99.51% gitlab.com/slon/shad-go/varfmt.BenchmarkSprintf.func1 0 0% 99.37% 716.73MB 99.51% testing.(*B).launch 0 0% 99.37% 716.73MB 99.51% testing.(*B).runN (pprof) diff --git a/docs/create-mr-form.png b/docs/create-mr-form.png deleted file mode 100644 index a0384c1..0000000 Binary files a/docs/create-mr-form.png and /dev/null differ diff --git a/docs/create-mr.png b/docs/create-mr.png deleted file mode 100644 index fc7e310..0000000 Binary files a/docs/create-mr.png and /dev/null differ diff --git a/docs/edit-and-fork.png b/docs/edit-and-fork.png deleted file mode 100644 index 213cbab..0000000 Binary files a/docs/edit-and-fork.png and /dev/null differ diff --git a/docs/edit-in-place.png b/docs/edit-in-place.png new file mode 100644 index 0000000..42b45e3 Binary files /dev/null and b/docs/edit-in-place.png differ diff --git a/docs/gitfame_review_comments.md b/docs/gitfame_review_comments.md index b8819dd..fcc5a28 100644 --- a/docs/gitfame_review_comments.md +++ b/docs/gitfame_review_comments.md @@ -63,8 +63,8 @@ import ( "flag" "log" - "gitlab.com/manytask/itmo-go/public/gitfame/configs" - "gitlab.com/manytask/itmo-go/public/gitfame/internal" + "gitlab.com/slon/shad-go/gitfame/configs" + "gitlab.com/slon/shad-go/gitfame/internal" "github.com/spf13/pflag" @@ -81,8 +81,8 @@ import ( "github.com/spf13/pflag" - "gitlab.com/manytask/itmo-go/public/gitfame/configs" - "gitlab.com/manytask/itmo-go/public/gitfame/internal" + "gitlab.com/slon/shad-go/gitfame/configs" + "gitlab.com/slon/shad-go/gitfame/internal" ) ``` diff --git a/docs/syllabus.md b/docs/syllabus.md index 3e9789a..ef9d83c 100644 --- a/docs/syllabus.md +++ b/docs/syllabus.md @@ -48,7 +48,7 @@ Low-level programming. unsafe. Package binary. bytes.Buffer. cgo, syscall. 11. Архитектура GC. Write barrier. Stack growth. GC pause. GOGC. sync.Pool. Шедулер - горутин. GOMACPROCS. Утечка тредов. + горутин. GOMAXPROCS. Утечка тредов. 12. Go tooling. pprof. CPU and Memory profiling. Кросс-компиляция. GOOS, GOARCH. CGO_ENABLED=0. Build tags. go modules. godoc. Code generation. diff --git a/dupcall/dupcall_test.go b/dupcall/dupcall_test.go index 9712850..8849ec4 100644 --- a/dupcall/dupcall_test.go +++ b/dupcall/dupcall_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gitlab.com/slon/shad-go/tools/testtool" "go.uber.org/goleak" ) @@ -38,6 +39,23 @@ func TestCall_Simple(t *testing.T) { require.Equal(t, 2, called) } +func TestCall_NoBusyWait(t *testing.T) { + done := make(chan struct{}) + defer close(done) + + var call Call + for i := 0; i < 10; i++ { + go func() { + _, _ = call.Do(context.Background(), func(ctx context.Context) (interface{}, error) { + <-done + return nil, nil + }) + }() + } + + testtool.VerifyNoBusyGoroutines(t) +} + func TestCall_Dedup(t *testing.T) { defer goleak.VerifyNone(t) diff --git a/excelwriter/README.md b/excelwriter/README.md new file mode 100644 index 0000000..3d32a7c --- /dev/null +++ b/excelwriter/README.md @@ -0,0 +1,67 @@ +# excelwriter [reflect] + +В этой задаче нужно обернуть библиотеку для работы с exel'ем в reflect, реализовав интерфейс для построчной записи go объектов в excel +```go +type Writer interface { + WriteRow(r any) error +} +``` +r — это либо структура, либо map[smth]any, либо указатель на что-то из этого. + +smth — это либо строка, либо тип реализующий [TextMarshaler](https://pkg.go.dev/encoding#TextMarshaler) + +Как должны сериализовываться поля структур подробно написано в интерфейсе. +Всё, что не специфицировано в доке и не проверяется тестами можно делать как сочтёте разумным. + +Также нужно реализовать конструктор +```go +func New(f *excelize.File) Writer { + panic("implement me") +} +``` +принимающий на вход инициализированный excel клиент. +Можно считать, что excel файл изначально пустой у которого создана 1 страница. Все записи нужно делать в ней. + +Пример использования +```go +type Movie struct { + Title string + Year int `xlsx:"release_year"` +} + +func StoreMovies() { + f := excelize.NewFile() + _, _ = f.NewSheet("Sheet1") + + w := excelwriter.New(f) + _ = w.WriteRow(&Movie{Title: "Blade Runner", Year: 1982}) + _ = w.WriteRow(&Movie{Title: "Blade Runner 2049", Year: 2017}) + _ = w.WriteRow(map[string]any{"title": "Into the wild", "release_year": 2007}) + + out, _ := os.Create("/tmp/movie.xlsx") + _, _ = f.WriteTo(out) +} +``` + +В результате будет создан excel документ со следующим содержимым +``` +title release_year +Blade Runner 1982 +Blade Runner 2049 2017 +Into the wild 2007 +``` + +В первой строке хранятся имена колонок, которые вычисляются из имён полей, тэгов и ключей map'ов. + +Разные структуры могут превращаться в разные наборы колонок. +Для каждого уникального имени должна быть ровно одна колонка, их нужно "создавать" по мере возникновения. + +Новые ключи каждого конкретного мапа добавляются в колонки в отсортированном порядке, чтобы при перезапусках на одних и тех же данных получались одинаковые excel'ки. + +Помимо имён полей в xlsx тэгах для числовых полей нужно поддержать стили форматирования. +Например, в excel нет отдельного типа для дат. Дата — это 15-и значный double (excel тип Number) со стилем форматирования `d-mmm-yy`. Библиотека для работы с excel'ем определяет [наборы популярных стилей](https://pkg.go.dev/github.com/xuri/excelize/v2#File.NewStyle) в виде enum'а `15 d-mmm-yy`. Это число 15 и нужно поддержать в тэге `xslx:"date,numfmt:15"`. + +## Вопросы со звёздочкой +1. Как бы вы поддержали в тэгах стили форматирования ячеек (excelize.Fill, excelize.Border ...)? +2. Как бы вы поддержали в тэгах кастомные стили форматирования числовых значений, те, что не входят в стандартный набор, например `0,"K"`? +3. Как мог бы выглядеть Reader, совместимый с Writer'ом, читающий строчки из excel в Go структуры и map'ы? diff --git a/excelwriter/writer.go b/excelwriter/writer.go new file mode 100644 index 0000000..e051c9f --- /dev/null +++ b/excelwriter/writer.go @@ -0,0 +1,48 @@ +//go:build !solution + +package excelwriter + +import ( + "github.com/xuri/excelize/v2" +) + +type Writer interface { + // WriteRow appends struct fields or map values to excel sheet. + // + // Integers and floats are encoded as excel type Number. + // Strings are encoded as excel type Text. + // Booleans are encoded as excel type Logical. + // + // Pointer values are encoded as the value pointed to. A nil pointer is skipped. + // + // Values implementing encoding.TextMarshaler interface are encoded as excel Text. + // + // Interface values are encoded as the value contained in the interface. A nil interface is skipped. + // + // Channels and functions are skipped. + // + // Structs, maps, slices and arrays are marshaled into json and encoded as excel Text. + // + // Encoding of each struct field can be customized by format string + // stored under the "xlsx" key in the field's tag. + // + // // Field appears in excel under column "my_field". + // Field int `xlsx:"my_field"` + // + // // Field appears in excel under column "my_field" formatted with predeclared style 15 ("d-mmm-yy"). + // // Only applicable for integers and floats. + // Field int `xlsx:"my_field,numfmt:15"` + // + // // Field is ignored by this package + // Field int `xlsx:"-"` + // + // The first row is reserved for column names. + // For structs column name must be either lowercase field name or the name from "xlsx" tag if present. + // For maps column name is a map key. + // If map key implements encoding.TextMarshaler then column name is string(key.MarshalText()). + WriteRow(r any) error +} + +func New(f *excelize.File) Writer { + panic("implement me") +} diff --git a/excelwriter/writer_test.go b/excelwriter/writer_test.go new file mode 100644 index 0000000..5be5174 --- /dev/null +++ b/excelwriter/writer_test.go @@ -0,0 +1,268 @@ +package excelwriter_test + +import ( + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/require" + "github.com/xuri/excelize/v2" + + "gitlab.com/slon/shad-go/excelwriter" +) + +const Sheet = "Sheet1" + +type MyInt int + +type Basic struct { + I int `xlsx:"i"` + UI uint `xlsx:"ui"` + I16 int16 `xlsx:"i_16"` + UI16 uint16 `xlsx:"ui_16"` + I32 int32 `xlsx:"i_32"` + UI32 uint32 `xlsx:"ui_32"` + I64 int64 `xlsx:"i_64"` + UI64 uint64 `xlsx:"ui_64"` + + Float float32 `xlsx:"float"` + Double float64 `xlsx:"double"` + Bool bool `xlsx:"bool"` + String string `xlsx:"string"` + + MyInt int `xlsx:"my_int"` +} + +type Inner struct { + Name string `xlsx:"name"` +} + +type TextInt int + +func (i TextInt) MarshalText() ([]byte, error) { + return []byte("__" + fmt.Sprint(i) + "__"), nil +} + +type TextStruct struct { + V string +} + +func (s TextStruct) MarshalText() (text []byte, err error) { + return []byte("__" + s.V + "__"), nil +} + +func TestWriter_basic(t *testing.T) { + f := excelize.NewFile() + _, err := f.NewSheet(Sheet) + require.NoError(t, err) + + w := excelwriter.New(f) + + b := &Basic{ + I: -1, + UI: 1, + I16: -16, + UI16: 16, + I32: -32, + UI32: 32, + I64: -64, + UI64: 64, + + Float: -2.5, + Double: 5.5, + Bool: true, + String: "hello", + + MyInt: 23, + } + require.NoError(t, w.WriteRow(b)) + + storeFile(t, f, "basic") + + rows := readAll(t, f, true) + require.Equal(t, []string{"i", "ui", "i_16", "ui_16", "i_32", "ui_32", "i_64", "ui_64", "float", "double", "bool", "string", "my_int"}, rows[0]) + require.Equal(t, []string{"-1", "1", "-16", "16", "-32", "32", "-64", "64", "-2.5", "5.5", "1", "hello", "23"}, rows[1]) +} + +func TestWriter_map(t *testing.T) { + f := excelize.NewFile() + _, err := f.NewSheet(Sheet) + require.NoError(t, err) + + w := excelwriter.New(f) + + require.NoError(t, w.WriteRow(map[string]any{ + "id": 29, + "name": "hello", + "title": "yo", + })) + + require.NoError(t, w.WriteRow(map[string]any{})) + + require.NoError(t, w.WriteRow(map[TextStruct]any{ + {"id"}: 18, + {"name"}: "tm", + })) + + storeFile(t, f, "map") + + rows := readAll(t, f, true) + require.Equal(t, []string{"id", "name", "title", "__id__", "__name__"}, rows[0]) + require.Equal(t, []string{"29", "hello", "yo"}, rows[1]) + require.Equal(t, []string{"", "", "", "18", "tm"}, rows[2]) +} + +type E struct { + ID string `xlsx:"id"` + NoTag string + Skipped int `xlsx:"-"` + private float32 `xlsx:"private"` + + TextInt TextInt `xlsx:"text-int"` + TextStruct TextStruct `xlsx:"text-struct"` + + Struct Inner `xlsx:"inner"` + StructPtr *Inner `xlsx:"inner-ptr"` + + Slice []int `xlsx:"slice"` + Array [2]int `xlsx:"arr"` + + Map map[string]string `xlsx:"map"` + TMMap map[TextStruct]string `xlsx:"tm-map"` + + F func() `xlsx:"func"` + Ch chan int `xlsx:"chan"` +} + +func TestWriter_elaborate(t *testing.T) { + f := excelize.NewFile() + _, err := f.NewSheet("Sheet1") + require.NoError(t, err) + + w := excelwriter.New(f) + + e := &E{ + ID: "42", + NoTag: "no-tag", + Skipped: 29, + private: 2, + TextInt: 77, + TextStruct: TextStruct{V: "text-struct"}, + Struct: Inner{Name: "inner"}, + StructPtr: &Inner{Name: "inner-ptr"}, + Slice: []int{1, 2, 3}, + Array: [2]int{4, 5}, + Map: map[string]string{"foo": "bar"}, + TMMap: map[TextStruct]string{{"foo"}: "bar"}, + F: func() { fmt.Println("hello") }, + Ch: make(chan int, 10), + } + require.NoError(t, w.WriteRow(e)) + + storeFile(t, f, "elaborate") + + rows := readAll(t, f, true) + require.Equal(t, []string{"id", "notag", "private", "text-int", "text-struct", "inner", "inner-ptr", "slice", "arr", "map", "tm-map"}, rows[0]) + require.Equal(t, []string{"42", "no-tag", "2", "__77__", "__text-struct__", `{"Name":"inner"}`, `{"Name":"inner-ptr"}`, "[1,2,3]", "[4,5]", `{"foo":"bar"}`, `{"__foo__":"bar"}`}, rows[1]) +} + +func TestWriter_ptr(t *testing.T) { + f := excelize.NewFile() + _, err := f.NewSheet(Sheet) + require.NoError(t, err) + + w := excelwriter.New(f) + + require.NoError(t, w.WriteRow(struct{ Name string }{"foo"})) + require.NoError(t, w.WriteRow(&struct{ Name string }{"bar"})) + require.NoError(t, w.WriteRow(map[string]string{"name": "baz"})) + require.NoError(t, w.WriteRow(&map[string]string{"name": "qux"})) + + storeFile(t, f, "ptr") + + rows := readAll(t, f, true) + require.Equal(t, []string{"name"}, rows[0]) + require.Equal(t, []string{"foo"}, rows[1]) + require.Equal(t, []string{"bar"}, rows[2]) + require.Equal(t, []string{"baz"}, rows[3]) + require.Equal(t, []string{"qux"}, rows[4]) +} + +func TestWriter_unsupported(t *testing.T) { + f := excelize.NewFile() + _, err := f.NewSheet("Sheet1") + require.NoError(t, err) + + w := excelwriter.New(f) + + require.Error(t, w.WriteRow(2)) + require.Error(t, w.WriteRow(nil)) + var b *Basic + require.Error(t, w.WriteRow(b)) +} + +type S struct { + P float64 `xlsx:"percent,numfmt:9"` + D int `xlsx:"date,numfmt:15"` + D2 int `xlsx:",numfmt:15"` + T float64 `xlsx:"time,numfmt:22"` + Y int `xlsx:"jpy,numfmt:194"` +} + +func TestWriter_style(t *testing.T) { + f := excelize.NewFile() + _, err := f.NewSheet("Sheet1") + require.NoError(t, err) + + w := excelwriter.New(f) + + s := &S{ + P: 0.5, + D: 100, + D2: 100, + T: 100.5, + Y: 200, + } + require.NoError(t, w.WriteRow(s)) + + storeFile(t, f, "style") + + rows := readAll(t, f, false) + require.Equal(t, []string{"percent", "date", "d2", "time", "jpy"}, rows[0]) + require.Equal(t, []string{"50%", "9-Apr-00", "9-Apr-00", "4/9/00 12:00", "¥200.00"}, rows[1]) +} + +func readAll(t *testing.T, f *excelize.File, raw bool) [][]string { + t.Helper() + + var out [][]string + + rows, err := f.Rows(Sheet) + require.NoError(t, err) + + var opts []excelize.Options + if raw { + opts = append(opts, excelize.Options{RawCellValue: true}) + } + + for i := 1; rows.Next(); i++ { + row, err := rows.Columns(opts...) + require.NoError(t, err) + + out = append(out, row) + } + + return out +} + +func storeFile(t *testing.T, f *excelize.File, prefix string) { + t.Helper() + + out, err := os.CreateTemp("/tmp", prefix+"-*.xlsx") + require.NoError(t, err) + + _, err = f.WriteTo(out) + require.NoError(t, err) + + t.Logf("stored file in %s", out.Name()) +} diff --git a/externalsort/sort_test.go b/externalsort/sort_test.go index 0e3e125..e10952f 100644 --- a/externalsort/sort_test.go +++ b/externalsort/sort_test.go @@ -4,7 +4,6 @@ import ( "bufio" "bytes" "fmt" - "io/ioutil" "os" "path" "strings" @@ -12,7 +11,7 @@ import ( "github.com/stretchr/testify/require" - "gitlab.com/manytask/itmo-go/public/tools/testtool" + "gitlab.com/slon/shad-go/tools/testtool" ) func TestMerge(t *testing.T) { @@ -33,6 +32,32 @@ func TestMerge(t *testing.T) { 1 1 2 +`, + }, + { + name: "with empty lines", + in: []string{` +0`, ` + +1 +1 +1`, ` + + +0 +2`}, + out: ` + + + + + +0 +0 +1 +1 +1 +2 `, }, } { @@ -65,7 +90,7 @@ func TestSort(t *testing.T) { testDir := path.Join("./testdata", "sort") readTestCase := func(dir string) (in []string, out string) { - files, err := ioutil.ReadDir(dir) + files, err := os.ReadDir(dir) require.NoError(t, err) for _, f := range files { @@ -84,7 +109,7 @@ func TestSort(t *testing.T) { testCaseDir := path.Join(testDir, d) t.Run(d, func(t *testing.T) { - tmpDir, err := ioutil.TempDir("", fmt.Sprintf("sort%s-", d)) + tmpDir, err := os.MkdirTemp("", fmt.Sprintf("sort%s-", d)) require.NoError(t, err) defer func() { _ = os.RemoveAll(tmpDir) }() @@ -95,7 +120,7 @@ func TestSort(t *testing.T) { w := bufio.NewWriter(&buf) require.NoError(t, Sort(w, in...)) - expected, err := ioutil.ReadFile(out) + expected, err := os.ReadFile(out) require.NoError(t, err) require.NoError(t, w.Flush()) @@ -107,7 +132,7 @@ func TestSort(t *testing.T) { func listDirs(t *testing.T, dir string) []string { t.Helper() - files, err := ioutil.ReadDir(dir) + files, err := os.ReadDir(dir) require.NoError(t, err) var dirs []string @@ -134,11 +159,11 @@ func copyFiles(t *testing.T, in []string, dir string) []string { func copyFile(t *testing.T, f, dir string) string { t.Helper() - data, err := ioutil.ReadFile(f) + data, err := os.ReadFile(f) require.NoError(t, err) dst := path.Join(dir, path.Base(f)) - err = ioutil.WriteFile(dst, data, 0o644) + err = os.WriteFile(dst, data, 0644) require.NoError(t, err) return dst diff --git a/externalsort/testdata/.gitattributes b/externalsort/testdata/.gitattributes new file mode 100644 index 0000000..556f8c8 Binary files /dev/null and b/externalsort/testdata/.gitattributes differ diff --git a/fetchall/main_test.go b/fetchall/main_test.go index cc94d6d..3213694 100644 --- a/fetchall/main_test.go +++ b/fetchall/main_test.go @@ -17,10 +17,10 @@ import ( "github.com/stretchr/testify/require" - "gitlab.com/manytask/itmo-go/public/tools/testtool" + "gitlab.com/slon/shad-go/tools/testtool" ) -const fetchallImportPath = "gitlab.com/manytask/itmo-go/public/fetchall" +const fetchallImportPath = "gitlab.com/slon/shad-go/fetchall" var binCache testtool.BinCache diff --git a/fileleak/fileleak_test.go b/fileleak/fileleak_test.go index 3b2a9d8..8efeff5 100644 --- a/fileleak/fileleak_test.go +++ b/fileleak/fileleak_test.go @@ -3,7 +3,6 @@ package fileleak_test import ( "bytes" "fmt" - "io/ioutil" "net" "os" "syscall" @@ -11,8 +10,8 @@ import ( "github.com/stretchr/testify/require" - "gitlab.com/manytask/itmo-go/public/fileleak" - "gitlab.com/manytask/itmo-go/public/tools/testtool" + "gitlab.com/slon/shad-go/fileleak" + "gitlab.com/slon/shad-go/tools/testtool" ) type fakeT struct { @@ -75,7 +74,7 @@ func TestFileLeak_ReopenFile(t *testing.T) { checkLeak(t, true, func() { _ = f.Close() - ff, err := ioutil.TempFile("", "") + ff, err := os.CreateTemp("", "") require.NoError(t, err) f = ff }) @@ -129,6 +128,7 @@ func TestFileLeak_DupLeak(t *testing.T) { var err error fd, err = syscall.Dup(1) require.NoError(t, err) + }) } diff --git a/firegod/Dockerfile b/firegod/Dockerfile new file mode 100644 index 0000000..bd8236d --- /dev/null +++ b/firegod/Dockerfile @@ -0,0 +1,11 @@ +FROM golang:1.22 + +RUN ["mkdir", "-p", "/build"] + +WORKDIR /build + +COPY . . + +RUN ["go", "build", "-tags", "solution", "-o", "/firegod", "./firegod"] + +ENTRYPOINT [ "/firegod", "-http=0.0.0.0:8080" ] diff --git a/firegod/README.md b/firegod/README.md new file mode 100644 index 0000000..7194288 --- /dev/null +++ b/firegod/README.md @@ -0,0 +1,55 @@ +# firegod + +В этой задаче вам нужно научиться пользоваться связкой prometheus+grafana для отладки собственного кода. + +Вам дан код сервиса. Нужно добавить в него метрики, и потом используя графану с помощью графиков ответить на ряд вопросов. + +В этой задаче нет автоматической проверки. Чтобы получить оценку, нужно закоммитить свои ответы вместе со скриншотами в репозиторий, и поменять значение константы в `Solved` в файле `main.go` на `true`. + +## Окружение + +В файле `docker-compose.yaml` описан тестовый стенд. + +- `prometheus` - контейнер с прометеем, который собирает метрики и выполняет запросы над ними. +- `grafana` - контейнер с графаной, дающий удобный `Web UI` для работы с прометеем. +- `my_service` - 5 реплик вашего сервиса. + +Чтобы запустит тестовый стенд, выполните команду `docker compose up --build`. Чтобы перезапустить стенд, остановите `docker compose` нажав `Ctrl+C` и перезапустите команду. + +После запуска стенда, проверьте что: + - [targets](http://localhost:9090/targets) показывает правильный список процессов. Один прометей в состоянии `up` и 5 копий вашего сервиса в состоянии `down` с ошибкой `server returned HTTP status 404 Not Found`. + - [grafana](http://localhost:3000/explore) пускает вас в интерфейс с логином `admin` и паролем `grafana`, а на странице Explore видно какие-то метрики (например `up`). + +## Сервис + +В пакете `dontlook` находится код сервиса. В него смотреть *нельзя*. + +Вам нужно дописать код сбора и экспорта метрик в файл `main.go`. + +1. Сделайте так, чтобы метрики экспортировались по запросу `GET /metrics`. +2. Включите экспорт метрик go рантайма и процесса (если они уже не экспортируются по дефолту). +3. Добавьте middleware записывающий метрики из http хендлеров. + +## Вопросы + +1. Сколько процессов каких сервисов подключено к прометею? (пример) + +**Ответ**: 1 прометей и 5 моих сервисов. + +![](screenshots/up.png) + +2. Какой процесс постоянно перезапускается? + +3. В каком процесс есть утечка файловых дескрипторов? + +4. В каком процессе есть утечка памяти? + +5. В каком процессе утекают горутины? + +6. Какой хендлер пятисотит больше всех? + +7. Сколько всего запросов в секунду приходит в сервис? + +8. Какой хендлер медленнее всех отвечает, если сравнивать по 90-ой перцентиле времени ответа? + +9. Какой хендлер генерирует больше всего трафика? diff --git a/firegod/docker-compose.yaml b/firegod/docker-compose.yaml new file mode 100644 index 0000000..1d98a7d --- /dev/null +++ b/firegod/docker-compose.yaml @@ -0,0 +1,62 @@ +services: + prometheus: + image: prom/prometheus + container_name: prometheus + command: + - '--config.file=/etc/prometheus/prometheus.yml' + ports: + - 9090:9090 + restart: unless-stopped + volumes: + - ./prometheus:/etc/prometheus + + grafana: + image: grafana/grafana + container_name: grafana + ports: + - 3000:3000 + restart: unless-stopped + environment: + - GF_SECURITY_ADMIN_USER=admin + - GF_SECURITY_ADMIN_PASSWORD=grafana + volumes: + - ./grafana:/etc/grafana/provisioning/datasources + + my-service-0: &service + build: + context: .. + dockerfile: firegod/Dockerfile + restart: always + deploy: + resources: + limits: + cpus: '0.5' + memory: 100M + + container_name: my-service-0 + environment: + - REPLICA=0 + + my-service-1: + <<: *service + container_name: my-service-1 + environment: + - REPLICA=1 + + my-service-2: + <<: *service + container_name: my-service-2 + environment: + - REPLICA=2 + + my-service-3: + <<: *service + container_name: my-service-3 + environment: + - REPLICA=3 + + my-service-4: + <<: *service + container_name: my-service-4 + environment: + - REPLICA=4 diff --git a/firegod/dontlook/itoldyounottolook.go b/firegod/dontlook/itoldyounottolook.go new file mode 100644 index 0000000..7d05185 --- /dev/null +++ b/firegod/dontlook/itoldyounottolook.go @@ -0,0 +1,111 @@ +package dontlook + +import ( + "bytes" + "fmt" + "io" + "net" + "net/http" + "os" + "strings" + "sync/atomic" + "time" + + "github.com/go-chi/chi/v5" +) + +func NewService(r chi.Router) { + replica := os.Getenv("REPLICA") + + switch replica { + case "0": + go func() { + for { + go func() { select {} }() + + time.Sleep(time.Millisecond * 100) + } + }() + + case "2": + go func() { + var buf []string + for i := 0; true; i++ { + buf = append(buf, strings.Repeat("f", 1<<20)) + _ = buf + + time.Sleep(time.Millisecond * 100 * time.Duration(i)) + } + }() + + case "3": + go func() { + for { + _, _ = net.Dial("tcp", "localhost:8080") + time.Sleep(time.Millisecond * 10) + } + }() + + case "4": + go func() { + time.Sleep(time.Second * 15) + os.Exit(1) + }() + } + + runClient := func(getUrl func() string) { + for { + go func() { + rsp, err := http.Get(fmt.Sprintf("http://localhost:8080%s", getUrl())) + if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + return + } + + _, _ = io.ReadAll(rsp.Body) + _ = rsp.Body.Close() + }() + + time.Sleep(time.Microsecond * 100) + } + } + + r.Get("/apple", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + time.Sleep(time.Millisecond * 100) + _, _ = w.Write([]byte("OK")) + }) + go runClient(func() string { return "/apple" }) + + r.Get("/banana", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + _, _ = w.Write(bytes.Repeat([]byte("f"), 1<<10)) + + if replica == "0" { + time.Sleep(time.Second) + } + }) + go runClient(func() string { return "/banana" }) + + var k atomic.Int32 + r.Get("/orange", func(w http.ResponseWriter, r *http.Request) { + if k.Add(1)%100 == 0 { + w.WriteHeader(500) + } else { + w.WriteHeader(200) + } + + }) + go runClient(func() string { return "/orange" }) + + r.Get("/kiwi/{id}", func(w http.ResponseWriter, r *http.Request) { + if replica == "3" { + w.WriteHeader(200) + } else { + w.WriteHeader(500) + } + }) + + var i atomic.Int32 + go runClient(func() string { return fmt.Sprintf("/kiwi/%d", i.Add(1)) }) +} diff --git a/firegod/grafana/datasource.yml b/firegod/grafana/datasource.yml new file mode 100644 index 0000000..d7b82868 --- /dev/null +++ b/firegod/grafana/datasource.yml @@ -0,0 +1,9 @@ +apiVersion: 1 + +datasources: +- name: Prometheus + type: prometheus + url: http://prometheus:9090 + isDefault: true + access: proxy + editable: true diff --git a/firegod/main.go b/firegod/main.go new file mode 100644 index 0000000..59d5dc6 --- /dev/null +++ b/firegod/main.go @@ -0,0 +1,24 @@ +package main + +import ( + "flag" + "log" + "net/http" + + "github.com/go-chi/chi/v5" + "gitlab.com/slon/shad-go/firegod/dontlook" +) + +var Solved = false + +var flagPort = flag.String("http", "", "") + +var router = chi.NewRouter() + +func main() { + flag.Parse() + + dontlook.NewService(router) + + log.Fatal(http.ListenAndServe(*flagPort, router)) +} diff --git a/firegod/main_test.go b/firegod/main_test.go new file mode 100644 index 0000000..6dc5e46 --- /dev/null +++ b/firegod/main_test.go @@ -0,0 +1,11 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestFiregod(t *testing.T) { + require.True(t, Solved) +} diff --git a/firegod/prometheus/prometheus.yml b/firegod/prometheus/prometheus.yml new file mode 100644 index 0000000..b68c191 --- /dev/null +++ b/firegod/prometheus/prometheus.yml @@ -0,0 +1,36 @@ +global: + scrape_interval: 5s + evaluation_interval: 5s + scrape_timeout: 1s + +alerting: + alertmanagers: + - static_configs: + - targets: [] + scheme: http + timeout: 1s + api_version: v1 + +scrape_configs: +- job_name: prometheus + honor_timestamps: true + scrape_interval: 5s + scrape_timeout: 1s + metrics_path: /metrics + scheme: http + static_configs: + - targets: + - localhost:9090 +- job_name: my-service + honor_timestamps: true + scrape_interval: 5s + scrape_timeout: 1s + metrics_path: /metrics + scheme: http + static_configs: + - targets: + - my-service-0:8080 + - my-service-1:8080 + - my-service-2:8080 + - my-service-3:8080 + - my-service-4:8080 diff --git a/firegod/screenshots/up.png b/firegod/screenshots/up.png new file mode 100644 index 0000000..e34b5ec Binary files /dev/null and b/firegod/screenshots/up.png differ diff --git a/firewall/README.md b/firewall/README.md index dd1a8b1..b7c00a9 100644 --- a/firewall/README.md +++ b/firewall/README.md @@ -51,6 +51,6 @@ Forbidden ## Resources * project layout: https://github.com/golang-standards/project-layout -* reverse proxy: https://en.wikipedia.org/wiki/Reverse_proxy +* reverse proxy: https://pkg.go.dev/net/http/httputil#ReverseProxy * yaml: https://gopkg.in/yaml.v2 * regexp: https://golang.org/pkg/regexp/ diff --git a/firewall/cmd/firewall/main_test.go b/firewall/cmd/firewall/main_test.go index d9c220b..e36c184 100644 --- a/firewall/cmd/firewall/main_test.go +++ b/firewall/cmd/firewall/main_test.go @@ -3,7 +3,6 @@ package main import ( "fmt" "io" - "io/ioutil" "net/http" "net/http/httptest" "os" @@ -15,10 +14,10 @@ import ( "github.com/go-resty/resty/v2" "github.com/stretchr/testify/require" - "gitlab.com/manytask/itmo-go/public/tools/testtool" + "gitlab.com/slon/shad-go/tools/testtool" ) -const importPath = "gitlab.com/manytask/itmo-go/public/firewall/cmd/firewall" +const importPath = "gitlab.com/slon/shad-go/firewall/cmd/firewall" var binCache testtool.BinCache @@ -36,7 +35,7 @@ func storeConfig(t *testing.T, conf string) (filename string, cleanup func()) { t.Helper() filename = path.Join(os.TempDir(), testtool.RandomName()+".yaml") - err := ioutil.WriteFile(filename, []byte(conf), 0o777) + err := os.WriteFile(filename, []byte(conf), 0777) require.NoError(t, err) cleanup = func() { _ = os.Remove(filename) } diff --git a/forth/README.md b/forth/README.md index a6af625..88a4ddb 100644 --- a/forth/README.md +++ b/forth/README.md @@ -79,6 +79,18 @@ Stack: а `definition` состоит из известных слов и чисел, разделённых пробелами. Слова можно переопределять. +При реализации механизма определений обратите внимание на юнит-тест + +```go +{ + description: "no redefinition", + input: []string{": foo 5 ;", ": bar foo ;", ": foo 6 ;", "bar foo"}, + expected: []int{5, 6}, +}, +``` + +То есть семантика слова вычисляется непосредственно при определении и не меняется при переопределении "зависимостей". + ### Проверка решения Для запуска тестов нужно выполнить следующую команду: diff --git a/forth/eval_test.go b/forth/eval_test.go index 6f20226..09a3ead 100644 --- a/forth/eval_test.go +++ b/forth/eval_test.go @@ -99,6 +99,11 @@ var testCases = []testCase{ input: []string{"2 4 * 3 /"}, expected: []int{2}, }, + { + description: "add non-empty stack", + input: []string{"1 2 3 +"}, + expected: []int{1, 5}, + }, { description: "dup", input: []string{"1 dup"}, diff --git a/genericsum/genericsum_test.go b/genericsum/genericsum_test.go index 819eeb8..06ecaa9 100644 --- a/genericsum/genericsum_test.go +++ b/genericsum/genericsum_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/goleak" - "gitlab.com/manytask/itmo-go/public/genericsum" + "gitlab.com/slon/shad-go/genericsum" ) func TestMin(t *testing.T) { @@ -184,11 +184,42 @@ func TestIsHermitianMatrix(t *testing.T) { {7, 2, 12}, {9, 12, 19}, })) + assert.True(t, genericsum.IsHermitianMatrix([][]int8{ + {-1, 7, 9}, + {7, -2, 12}, + {9, 12, -19}, + })) + assert.True(t, genericsum.IsHermitianMatrix([][]uint16{ + {1, 7, 9}, + {7, 2, 12}, + {9, 12, 19}, + })) assert.False(t, genericsum.IsHermitianMatrix([][]int{ {1, 12, 8}, {3, 4, 7}, {8, 7, 11}, })) + assert.False(t, genericsum.IsHermitianMatrix([][]int32{ + {1, 112, 8}, + {-3, 4, -7}, + {8, 7, 11}, + })) + assert.False(t, genericsum.IsHermitianMatrix([][]uint64{ + {1, 12, 8}, + {3, 4, 7}, + {8, 7, 11}, + })) + + assert.True(t, genericsum.IsHermitianMatrix([][]float32{ + {1.0, 7.0, 9.0}, + {7.0, 2.0, 12.0}, + {9.0, 12.0, 19.0}, + })) + assert.False(t, genericsum.IsHermitianMatrix([][]float32{ + {1.0, 12.0, 8.0}, + {3.0, 4.0, 7.0}, + {8.0, 7.0, 11.0}, + })) assert.True(t, genericsum.IsHermitianMatrix([][]complex64{ {1, 3 + 2i}, {3 - 2i, 4}, diff --git a/gitfame/README.md b/gitfame/README.md index 2b37a00..8bd63ba 100644 --- a/gitfame/README.md +++ b/gitfame/README.md @@ -175,6 +175,11 @@ export PATH=$GOPATH/bin:$PATH После этого `gitfame` будет доступен всюду. +В реализации вы можете использовать сторонние библиотеки, которые уже доступны в нашем [`go.mod`](../go.mod). Менять `go.mod` нельзя. + +Весь репозиторий курса - это один go модуль с одним go.mod файлом в корне. Корню репозитория соответствует импорт путь `gitlab.com/slon/shad-go`. Если вы создадите пакет в директории `gitfame/internal/git`, то импортировать его нужно будет по пути `gitlab.com/slon/shad-go/gitfame/internal/git`. + + ### Code review comments Прочитайте и исправьте [распространённые ошибки](../docs/gitfame_review_comments.md). diff --git a/gitfame/test/integration/gitfame_test.go b/gitfame/test/integration/gitfame_test.go index 7b50657..492443b 100644 --- a/gitfame/test/integration/gitfame_test.go +++ b/gitfame/test/integration/gitfame_test.go @@ -2,7 +2,6 @@ package integration import ( "bytes" - "io/ioutil" "os" "os/exec" "path" @@ -14,10 +13,10 @@ import ( "github.com/stretchr/testify/require" "gopkg.in/yaml.v2" - "gitlab.com/manytask/itmo-go/public/tools/testtool" + "gitlab.com/slon/shad-go/tools/testtool" ) -const importPath = "gitlab.com/manytask/itmo-go/public/gitfame/cmd/gitfame" +const importPath = "gitlab.com/slon/shad-go/gitfame/cmd/gitfame" var binCache testtool.BinCache @@ -43,7 +42,7 @@ func TestGitFame(t *testing.T) { tc := ReadTestCase(t, filepath.Join(testsDir, dir)) t.Run(dir+"/"+tc.Name, func(t *testing.T) { - dir, err := ioutil.TempDir("", "gitfame-") + dir, err := os.MkdirTemp("", "gitfame-") require.NoError(t, err) defer func() { _ = os.RemoveAll(dir) }() @@ -75,7 +74,7 @@ func TestGitFame(t *testing.T) { func ListTestDirs(t *testing.T, path string) []string { t.Helper() - files, err := ioutil.ReadDir(path) + files, err := os.ReadDir(path) require.NoError(t, err) var names []string @@ -109,7 +108,7 @@ func ReadTestCase(t *testing.T, path string) *TestCase { desc := ReadTestDescription(t, path) - expected, err := ioutil.ReadFile(filepath.Join(path, "expected.out")) + expected, err := os.ReadFile(filepath.Join(path, "expected.out")) require.NoError(t, err) return &TestCase{TestDescription: desc, Expected: expected} @@ -126,7 +125,7 @@ type TestDescription struct { func ReadTestDescription(t *testing.T, path string) *TestDescription { t.Helper() - data, err := ioutil.ReadFile(filepath.Join(path, "description.yaml")) + data, err := os.ReadFile(filepath.Join(path, "description.yaml")) require.NoError(t, err) var desc TestDescription diff --git a/go.mod b/go.mod index 2298213..7d22a18 100644 --- a/go.mod +++ b/go.mod @@ -1,66 +1,80 @@ -module gitlab.com/manytask/itmo-go/public +module gitlab.com/slon/shad-go -go 1.18 +go 1.22.0 require ( github.com/felixge/httpsnoop v1.0.3 github.com/go-chi/chi/v5 v5.0.8 + github.com/go-git/go-git/v5 v5.11.0 github.com/go-redis/redis/v8 v8.11.5 github.com/go-resty/resty/v2 v2.1.0 github.com/gofrs/uuid v3.3.0+incompatible - github.com/golang/mock v1.4.1 - github.com/google/go-cmp v0.5.9 + github.com/golang/mock v1.6.0 + github.com/google/btree v1.1.2 + github.com/google/go-cmp v0.6.0 github.com/gorilla/handlers v1.4.2 github.com/gorilla/mux v1.7.4 github.com/gorilla/websocket v1.4.2 - github.com/jackc/pgx/v4 v4.6.0 - github.com/jonboulle/clockwork v0.1.0 + github.com/jackc/pgx/v5 v5.5.3 + github.com/jonboulle/clockwork v0.4.0 github.com/spf13/cobra v1.1.3 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.8.2 - go.uber.org/goleak v1.0.0 - go.uber.org/zap v1.14.0 + github.com/stretchr/testify v1.8.4 + go.uber.org/goleak v1.3.0 + go.uber.org/zap v1.26.0 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/perf v0.0.0-20191209155426-36b577b0eb03 - golang.org/x/sync v0.1.0 - golang.org/x/sys v0.7.0 - golang.org/x/tools v0.7.0 + golang.org/x/sync v0.6.0 + golang.org/x/sys v0.17.0 + golang.org/x/tools v0.18.0 google.golang.org/grpc v1.54.0 - google.golang.org/protobuf v1.30.0 + google.golang.org/protobuf v1.33.0 gopkg.in/yaml.v2 v2.4.0 ) require ( - github.com/BurntSushi/toml v0.3.1 // indirect + dario.cat/mergo v1.0.0 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect + github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cloudflare/circl v1.3.3 // indirect + github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgconn v1.5.0 // indirect - github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.0.1 // indirect - github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8 // indirect - github.com/jackc/pgtype v1.3.0 // indirect - github.com/kr/pretty v0.3.0 // indirect - github.com/lib/pq v1.10.0 // indirect - github.com/pkg/errors v0.9.1 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.8.0 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/richardlehane/mscfb v1.0.4 // indirect + github.com/richardlehane/msoleps v1.0.3 // indirect + github.com/sergi/go-diff v1.1.0 // indirect + github.com/skeema/knownhosts v1.2.1 // indirect github.com/stretchr/objx v0.5.0 // indirect - go.uber.org/atomic v1.5.0 // indirect - go.uber.org/multierr v1.3.0 // indirect - go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee // indirect - golang.org/x/crypto v0.5.0 // indirect - golang.org/x/lint v0.0.0-20190930215403-16217165b5de // indirect - golang.org/x/mod v0.9.0 // indirect - golang.org/x/net v0.9.0 // indirect - golang.org/x/text v0.9.0 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 // indirect + github.com/xuri/excelize/v2 v2.8.1 // indirect + github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect + go.uber.org/multierr v1.10.0 // indirect + golang.org/x/crypto v0.19.0 // indirect + golang.org/x/mod v0.15.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/text v0.14.0 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/tools v0.0.1-2019.2.3 // indirect ) diff --git a/go.sum b/go.sum index 5f2d924..727e9e2 100644 --- a/go.sum +++ b/go.sum @@ -11,38 +11,50 @@ cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7 cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190129172621-c8b1d7a94ddf/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/aclements/go-gg v0.0.0-20170118225347-6dbb4e4fefb0/go.mod h1:55qNq4vcpkIuHowELi5C8e+1yUHtoLoOUR9QU5j7Tes= github.com/aclements/go-moremath v0.0.0-20161014184102-0ff62e0875ff/go.mod h1:idZL3yvz4kzx1dsBOAC+oYv6L92P1oFEhUXUB1A/lwQ= 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/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= 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/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -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/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 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/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/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 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= @@ -50,14 +62,29 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= +github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= +github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= +github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -68,18 +95,19 @@ github.com/go-resty/resty/v2 v2.1.0 h1:Z6IefCpUMfnvItVJaJXWv/pMiiD11So35QgwEELsl github.com/go-resty/resty/v2 v2.1.0/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 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 v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84= github.com/gofrs/uuid v3.3.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/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.1 h1:ocYkMQY5RrXTYgXl7ICpV0IXwlEQGwKIsery4gyXa1U= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -93,11 +121,13 @@ github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2 github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -137,78 +167,39 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= -github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= -github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -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.5.0 h1:oFSOilzIZkyg787M1fEmyMfOUUvwj0daqYMfaWwNL4o= -github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -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/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/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= -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 h1:Rdjp4NFjwHnEslx2b66FfCI2S0LhO4itac3hXz6WX9M= -github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8 h1:Q3tB+ExeflWUW7AFcAhXqk40s9mnNYLk1nOkKNZ5GnU= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/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.3.0 h1:l8JvKrby3RI7Kg3bYEeU9TA4vqC38QDpFCfcrC7KuN0= -github.com/jackc/pgtype v1.3.0/go.mod h1:b0JqxHvPmljG+HQ5IsvQ0yqeSi4nGcDTVjFoiLDb0Ik= -github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= -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.6.0 h1:Fh0O9GdlG4gYpjpwOqjdEodJUQM9jzN3Hdv7PN0xmm0= -github.com/jackc/pgx/v4 v4.6.0/go.mod h1:vPh43ZzxijXUVJ+t/EmXBtFmbFVO72cuneCT9oAlxAg= -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/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.5.3 h1:Ces6/M3wbDXYpM8JyyPD57ivTtJACFZJd885pdIaV2s= +github.com/jackc/pgx/v5 v5.5.3/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= +github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 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/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 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/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 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/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/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.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E= -github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -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-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -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-sqlite3 v0.0.0-20161215041557-2d44decb4941/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -222,14 +213,20 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= 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/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= 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= @@ -239,31 +236,40 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM= +github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= +github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= +github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM= +github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= 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/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 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= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -279,50 +285,54 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= 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/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 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/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 h1:Chd9DkqERQQuHpXjR/HSV1jLZA6uaoiwwH3vSuF3IW0= +github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI= +github.com/xuri/excelize/v2 v2.8.1 h1:pZLMEwK8ep+CLIUWpWmvW8IWE/yxqG0I1xcN6cVMGuQ= +github.com/xuri/excelize/v2 v2.8.1/go.mod h1:oli1E4C3Pa5RXg1TBXn4ENCXDV5JUMlBluUhG7c+CEE= +github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 h1:qhbILQo1K3mphbwKh1vNm4oGezE1eF9fQWmNiIpSfI4= +github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -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 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/goleak v1.0.0 h1:qsup4IcBdlmsnGfqyLl4Ntn3C2XCCuKAE7DwHpScyUo= -go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= -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/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.14.0 h1:/pduUoebOeeJzTDFuoMgC6nRkiasr1sBCIEorly7m4o= -go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/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-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -338,14 +348,16 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -361,9 +373,15 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/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-20190628185345-da137c7871d7/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.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -375,8 +393,11 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -384,25 +405,46 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/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.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +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/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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= @@ -414,26 +456,23 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/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-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -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/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/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-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-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.0.0-20170206182103-3d017632ea10/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -466,16 +505,21 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 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= @@ -488,8 +532,5 @@ gopkg.in/yaml.v3 v3.0.1/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.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/gossip/gossip.go b/gossip/gossip.go index e314555..01268e9 100644 --- a/gossip/gossip.go +++ b/gossip/gossip.go @@ -5,7 +5,8 @@ package gossip import ( "time" - "gitlab.com/manytask/itmo-go/public/gossip/meshpb" + "gitlab.com/slon/shad-go/gossip/meshpb" + "google.golang.org/grpc" ) type PeerConfig struct { diff --git a/gossip/gossip_test.go b/gossip/gossip_test.go index 2baaa44..233b44d 100644 --- a/gossip/gossip_test.go +++ b/gossip/gossip_test.go @@ -8,8 +8,8 @@ import ( "time" "github.com/stretchr/testify/require" - "gitlab.com/manytask/itmo-go/public/gossip" - "gitlab.com/manytask/itmo-go/public/gossip/meshpb" + "gitlab.com/slon/shad-go/gossip" + "gitlab.com/slon/shad-go/gossip/meshpb" "go.uber.org/goleak" "google.golang.org/grpc" ) diff --git a/gossip/meshpb/protocol.proto b/gossip/meshpb/protocol.proto index 2d0440c..edcd754 100644 --- a/gossip/meshpb/protocol.proto +++ b/gossip/meshpb/protocol.proto @@ -2,7 +2,7 @@ syntax = "proto3"; -option go_package = "gitlab.com/manytask/itmo-go/public/gossip/meshpb"; +option go_package = "gitlab.com/slon/shad-go/gossip/meshpb"; // PeerMeta is arbitrary message that is propagated with peer gossip. message PeerMeta { diff --git a/gzep/README.md b/gzep/README.md index 48d57b7..c6ab3bb 100644 --- a/gzep/README.md +++ b/gzep/README.md @@ -6,14 +6,14 @@ ``` goos: linux goarch: amd64 -pkg: gitlab.com/manytask/itmo-go/public/gzep +pkg: gitlab.com/slon/shad-go/gzep cpu: Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz BenchmarkEncodeSimple BenchmarkEncodeSimple-8 7047 176628 ns/op 813872 B/op 17 allocs/op BenchmarkEncode BenchmarkEncode-8 41706 32616 ns/op 19 B/op 0 allocs/op PASS -ok gitlab.com/manytask/itmo-go/public/gzep 3.625s +ok gitlab.com/slon/shad-go/gzep 3.625s ``` ### С чего начать? diff --git a/gzep/encode_test.go b/gzep/encode_test.go index 3308b36..211ad04 100644 --- a/gzep/encode_test.go +++ b/gzep/encode_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/require" - "gitlab.com/manytask/itmo-go/public/gzep" - "gitlab.com/manytask/itmo-go/public/tools/testtool" + "gitlab.com/slon/shad-go/gzep" + "gitlab.com/slon/shad-go/tools/testtool" ) func BenchmarkEncode(b *testing.B) { @@ -47,6 +47,7 @@ func TestEncode_RoundTrip(t *testing.T) { require.NoError(t, err, tc.in) require.Equal(t, tc.in, string(out)) }) + } } diff --git a/illegal/field_test.go b/illegal/field_test.go index a7aa76e..32d1f65 100644 --- a/illegal/field_test.go +++ b/illegal/field_test.go @@ -5,8 +5,8 @@ import ( "github.com/stretchr/testify/assert" - "gitlab.com/manytask/itmo-go/public/illegal" - "gitlab.com/manytask/itmo-go/public/illegal/internal" + "gitlab.com/slon/shad-go/illegal" + "gitlab.com/slon/shad-go/illegal/internal" ) func TestIllegalField(t *testing.T) { diff --git a/illegal/string_test.go b/illegal/string_test.go index 56670cd..d2514cc 100644 --- a/illegal/string_test.go +++ b/illegal/string_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - "gitlab.com/manytask/itmo-go/public/illegal" + "gitlab.com/slon/shad-go/illegal" ) func TestStringFromBytes(t *testing.T) { diff --git a/iprange/example_test.go b/iprange/example_test.go index fb64113..8fcd911 100644 --- a/iprange/example_test.go +++ b/iprange/example_test.go @@ -4,7 +4,7 @@ import ( "fmt" "log" - "gitlab.com/manytask/itmo-go/public/iprange" + "gitlab.com/slon/shad-go/iprange" ) func ExampleParseList() { diff --git a/keylock/README.md b/keylock/README.md index a330a41..f2ebaf0 100644 --- a/keylock/README.md +++ b/keylock/README.md @@ -4,7 +4,7 @@ В обычном `sync.Mutex` лок всего один. В один момент времени этот лок может находиться у одной горутины. В нашем примитиве локов может быть сколько угодно. Каждый лок мы идентифицируем -ключём - строкой. Каждая горутина приходит к нам со списком ключей и хочет захватить сразу +ключом - строкой. Каждая горутина приходит к нам со списком ключей и хочет захватить сразу все локи из этого списка. (Наша аналогия с `sync.Mutex` вовсе не значит, что нужно использовать `sync.Mutex` в реализации. Лучше использовать каналы, чтобы проще было реализовать отмену.) diff --git a/keylock/keylock_test.go b/keylock/keylock_test.go index 8ef35f4..d11b0c0 100644 --- a/keylock/keylock_test.go +++ b/keylock/keylock_test.go @@ -1,14 +1,19 @@ package keylock_test import ( + "fmt" + "math/rand" + "slices" "sync" "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/goleak" - "gitlab.com/manytask/itmo-go/public/keylock" + "gitlab.com/slon/shad-go/keylock" + "gitlab.com/slon/shad-go/tools/testtool" ) func timeout(d time.Duration) <-chan struct{} { @@ -57,6 +62,21 @@ func TestKeyLock_Progress(t *testing.T) { unlock1() } +func TestKeyLock_NoBusyWait(t *testing.T) { + defer goleak.VerifyNone(t) + l := keylock.New() + + _, unlock0 := l.LockKeys([]string{"a", "b"}, nil) + defer unlock0() + + go func() { + _, unlock := l.LockKeys([]string{"b", "c"}, nil) + unlock() + }() + + testtool.VerifyNoBusyGoroutines(t) +} + func TestKeyLock_DeadlockFree(t *testing.T) { const N = 10000 @@ -116,7 +136,7 @@ func TestKeyLock_SingleKeyStress(t *testing.T) { go func() { defer wg.Done() - for i := 0; i < N; i++ { + for j := 0; j < N; j++ { cancelled, unlock := l.LockKeys([]string{"a"}, timeout(time.Millisecond)) if !cancelled { unlock() @@ -127,3 +147,58 @@ func TestKeyLock_SingleKeyStress(t *testing.T) { wg.Wait() } + +func TestKeyLock_MutualExclusionStress(t *testing.T) { + const ( + N = 1000 + G = 100 + M = 15 + K = 3 + ) + + defer goleak.VerifyNone(t) + + locked := map[string]bool{} + var mu sync.Mutex + + l := keylock.New() + + var wg sync.WaitGroup + wg.Add(G) + + for i := 0; i < G; i++ { + go func() { + defer wg.Done() + + for j := 0; j < N; j++ { + keys := []string{} + for k := 0; k < K; k++ { + keys = append(keys, fmt.Sprint(rand.Intn(N))) + } + + slices.Sort(keys) + keys = slices.Compact(keys) + + _, unlock := l.LockKeys(keys, nil) + mu.Lock() + for _, key := range keys { + assert.False(t, locked[key]) + locked[key] = true + } + mu.Unlock() + + time.Sleep(time.Millisecond) + + mu.Lock() + for _, key := range keys { + locked[key] = false + } + mu.Unlock() + + unlock() + } + }() + } + + wg.Wait() +} diff --git a/keylock/speed_test.go b/keylock/speed_test.go index 7483193..c885e80 100644 --- a/keylock/speed_test.go +++ b/keylock/speed_test.go @@ -3,23 +3,9 @@ package keylock import ( "math/rand" "strconv" - "sync" "testing" ) -func BenchmarkMutex_Baseline(b *testing.B) { - var mu sync.Mutex - - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - mu.Lock() - _ = 0 - mu.Unlock() - } - }) -} - func BenchmarkKeyLock_SingleKey(b *testing.B) { l := New() diff --git a/lectures/00-intro/fetchall/fetchall.go b/lectures/00-intro/fetchall/fetchall.go index c49ca46..d692c24 100644 --- a/lectures/00-intro/fetchall/fetchall.go +++ b/lectures/00-intro/fetchall/fetchall.go @@ -3,7 +3,6 @@ package main import ( "fmt" "io" - "io/ioutil" "net/http" "os" "time" @@ -30,7 +29,7 @@ func fetch(url string, ch chan<- string) { } defer resp.Body.Close() // don't leak resources - nbytes, err := io.Copy(ioutil.Discard, resp.Body) + nbytes, err := io.Copy(io.Discard, resp.Body) if err != nil { ch <- fmt.Sprintf("while reading %s: %v", url, err) return diff --git a/lectures/00-intro/lecture.slide b/lectures/00-intro/lecture.slide index cc9fcd3..36dfd22 100644 --- a/lectures/00-intro/lecture.slide +++ b/lectures/00-intro/lecture.slide @@ -11,8 +11,7 @@ * Ссылки -.link https://wiki.yandex.ru/shad/groups/2018/Semester4/GoLang/ Вики страница -.link https://gitlab.com/manytask/itmo-go/public Репозиторий +.link https://github.com/slon/shad-go Репозиторий .link https://t.me/joinchat/BjrYSxdPJGtJdd1pae08Zg Чат курса в телеграме [[https://p.go.manytask.org]] - эти слайды. @@ -21,7 +20,7 @@ - 12+ занятий - Семинарские задания после каждой лекции. *Дедлайн*10*дней.* - 4 _больших_ домашних задания. *Дедлайн*3*недели.* -- Критерий оценки: *TODO*. +- Критерий оценки: *В*LMS* (>N домашек и >X% за семинары). * Hello world @@ -37,12 +36,25 @@ Systems Language +* История + +- 2009 go public announcement +- 2012 go 1.0 +- 2008 github launch +- 2011 C++11 +- 2011 pip initial release +- 2010 npm first release +- 2009 nodejs first release +- 2008 python3 +- 2006 rust project started +- 2015 rust 1.0 + * Современный мир - Море библиотек. Большие деревья зависимостей. : Нам нужен язык, который будет помогать контролировать сложность at large. - Архитектура построена вокруг сервисов, которые общаются по сети. -: Скорее вам придётся писать stateless сервис. Statefull сервисы общаются с базой данных по сети. +: Скорее вам придётся писать stateless сервис. Stateful сервисы общаются с базой данных по сети. - Многоядерные процессоры даже в телефонах. * Скорость разработки @@ -149,6 +161,8 @@ Language var s = "" var s string = "" +.link https://go.dev/blog/declaration-syntax Почему тип пишется после названия переменной + * uniq .play -edit uniq/uniq.go @@ -230,7 +244,7 @@ Pointers var s string p := &s - s2 = *p + s2 := *p var p Point p.X = 1 diff --git a/lectures/00-intro/urlfetch/urlfetch.go b/lectures/00-intro/urlfetch/urlfetch.go index 4136c33..b826eb2 100644 --- a/lectures/00-intro/urlfetch/urlfetch.go +++ b/lectures/00-intro/urlfetch/urlfetch.go @@ -2,7 +2,7 @@ package main import ( "fmt" - "io/ioutil" + "io" "net/http" "os" ) @@ -14,7 +14,7 @@ func main() { fmt.Fprintf(os.Stderr, "fetch: %v\n", err) os.Exit(1) } - b, err := ioutil.ReadAll(resp.Body) + b, err := io.ReadAll(resp.Body) resp.Body.Close() if err != nil { fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err) diff --git a/lectures/01-basics/github/github.go b/lectures/01-basics/github/github.go index ab81578..7399b84 100644 --- a/lectures/01-basics/github/github.go +++ b/lectures/01-basics/github/github.go @@ -3,6 +3,7 @@ package github import ( "encoding/json" "fmt" + "io" "net/http" "net/url" "strings" @@ -22,6 +23,10 @@ func SearchIssues(terms []string) (*IssuesSearchResult, error) { defer resp.Body.Close() if resp.StatusCode != http.StatusOK { + // The default HTTP client's Transport may not + // reuse HTTP/1.x "keep-alive" TCP connections if the Body is + // not read to completion and closed. + io.Copy(io.Discard, resp.Body) return nil, fmt.Errorf("search query failed: %s", resp.Status) } diff --git a/lectures/01-basics/lecture.slide b/lectures/01-basics/lecture.slide index 8aeef12..8e10572 100644 --- a/lectures/01-basics/lecture.slide +++ b/lectures/01-basics/lecture.slide @@ -21,14 +21,14 @@ Типы - int int8 int16 int32 int64 + any comparable int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr float32 float64 complex128 complex64 bool byte rune string error Функции - make len cap new append copy close delete + min max make len cap new append clear copy close delete complex real imag panic recover @@ -105,7 +105,7 @@ * new -`new(T)` создаёт новую переменную с типом `T`. +`new(T)` создаёт новую переменную с типом `*T`. func newInt() *int { return new(int) @@ -126,6 +126,9 @@ q := new(struct{}) fmt.Println(p == q) // "true" or "false", depending on implementation + a := [1_000_000_000]struct{}{} + fmt.Println(unsafe.Sizeof(a)) // 0 + * variable lifetime Память освобождается, после того как переменая становится недостижимой. @@ -146,12 +149,18 @@ *y = 1 } +.link https://habr.com/ru/companies/oleg-bunin/articles/676332/ Алгоритм для определения стек или куча для переменной + * type declaration type name underlying-type .play tempconv0/conv.go +- type alias + + type name = another-type + * packages - Файл `tempconv/types.go` @@ -170,9 +179,11 @@ * package initialization - var a = b + c // a initialized third, to 3 - var b = f() // b initialized second, to 2, by calling f - var c = 1 // c initialized first, to 1 + var ( + a = b + c // a initialized third, to 3 + b = f() // b initialized second, to 2, by calling f + c = 1 // c initialized first, to 1 + ) func f() int { return c + 1 } @@ -295,7 +306,7 @@ * bytes.Buffer - func intsToString(values []int) string { + func intsToBytes(values []int) []byte { var buf bytes.Buffer buf.WriteByte('[') for i, v := range values { @@ -305,7 +316,7 @@ fmt.Fprintf(&buf, "%d", v) } buf.WriteByte(']') - return buf.String() + return buf.Bytes() } * constants @@ -375,6 +386,13 @@ s := make([]int, 10) s = s[:0] s = s[:10] + s = s[:5:5] + s = s[:10] // panic + +- make эквивалентен следующему коду + + a := [10]int{} + s := a[:] * slices @@ -388,11 +406,11 @@ * slices var a, b []string - fmt.Println(a == b) + // a == nil && b == nil + fmt.Println(a == b) // invalid operation: a == b (slice can only be compared to nil) var c []int d := []int{} - fmt.Println(c != d) // c == nil && d != nil // len(c) == 0 && len(d) == 0 @@ -411,6 +429,8 @@ var a, b []int a = append(a, b...) + sCopy := append([]int(nil), s...) // use slices.Clone instead + * stack stack = append(stack, v) // push v @@ -419,6 +439,17 @@ stack = stack[:len(stack)-1] // pop +* queue + + queue = append(queue, v) // push v + + front := queue[0] // front of queue + + queue = queue[1:] // pop + +- O(1) амортизированное время всех операций +- Не очень эффективно по числу аллокаций + * copy func remove(slice []int, i int) []int { @@ -451,6 +482,8 @@ ages["bob"]++ _ = &ages["bob"] // compile error: cannot take address of map element + clear(ages) + * maps for name, age := range ages { diff --git a/lectures/02-interfaces/interfaces/embed.go b/lectures/02-interfaces/interfaces/embed.go new file mode 100644 index 0000000..761fc17 --- /dev/null +++ b/lectures/02-interfaces/interfaces/embed.go @@ -0,0 +1,21 @@ +package sort + +type Interface interface { + Len() int + Less(i, j int) bool + Swap(i, j int) +} + +func Reverse(data Interface) Interface { + return &reverse{data} +} + +type reverse struct { + // This embedded Interface permits Reverse to use the methods of + // another Interface implementation. + Interface +} + +func (r reverse) Less(i, j int) bool { + return r.Interface.Less(j, i) +} diff --git a/lectures/02-interfaces/lecture.slide b/lectures/02-interfaces/lecture.slide index 8581efc..fcb9696 100644 --- a/lectures/02-interfaces/lecture.slide +++ b/lectures/02-interfaces/lecture.slide @@ -162,10 +162,10 @@ Methods Сетеры/гетеры для простых типов не приветствуются. - type Point { x, y int } + type Point struct { x, y int } - func (p *Point) X() int { return x } - func (p *Point) Y() int { return y } + func (p *Point) X() int { return p.x } + func (p *Point) Y() int { return p.y } func (p *Point) SetX(x int) { p.x = x } func (p *Point) SetY(y int) { p.y = y } @@ -244,6 +244,12 @@ Methods Closer } +* Interface embedding in struct + +.play interfaces/embed.go + +.link https://pkg.go.dev/github.com/go-chi/chi/v5/middleware#WrapResponseWriter Daily-life example + * Interface satisfaction var w io.Writer diff --git a/lectures/03-goroutines/du1/main.go b/lectures/03-goroutines/du1/main.go index 5bed1ab..ba235e2 100644 --- a/lectures/03-goroutines/du1/main.go +++ b/lectures/03-goroutines/du1/main.go @@ -11,7 +11,6 @@ package main import ( "flag" "fmt" - "io/ioutil" "os" "path/filepath" ) @@ -58,7 +57,7 @@ func walkDir(dir string, fileSizes chan<- int64) { // dirents returns the entries of directory dir. func dirents(dir string) []os.FileInfo { - entries, err := ioutil.ReadDir(dir) + entries, err := os.ReadDir(dir) if err != nil { fmt.Fprintf(os.Stderr, "du1: %v\n", err) return nil diff --git a/lectures/03-goroutines/du2/main.go b/lectures/03-goroutines/du2/main.go index bb1e9cd..cfd4fe9 100644 --- a/lectures/03-goroutines/du2/main.go +++ b/lectures/03-goroutines/du2/main.go @@ -12,13 +12,12 @@ package main import ( "flag" "fmt" - "io/ioutil" "os" "path/filepath" "time" ) -//!+ +// !+ var verbose = flag.Bool("v", false, "show verbose progress messages") func main() { @@ -82,7 +81,7 @@ func walkDir(dir string, fileSizes chan<- int64) { // dirents returns the entries of directory dir. func dirents(dir string) []os.FileInfo { - entries, err := ioutil.ReadDir(dir) + entries, err := os.ReadDir(dir) if err != nil { fmt.Fprintf(os.Stderr, "du: %v\n", err) return nil diff --git a/lectures/03-goroutines/du3/main.go b/lectures/03-goroutines/du3/main.go index 42b3214..a4869f2 100644 --- a/lectures/03-goroutines/du3/main.go +++ b/lectures/03-goroutines/du3/main.go @@ -13,7 +13,6 @@ package main import ( "flag" "fmt" - "io/ioutil" "os" "path/filepath" "sync" @@ -22,7 +21,7 @@ import ( var vFlag = flag.Bool("v", false, "show verbose progress messages") -//!+ +// !+ func main() { // ...determine roots... @@ -82,7 +81,7 @@ func printDiskUsage(nfiles, nbytes int64) { // walkDir recursively walks the file tree rooted at dir // and sends the size of each found file on fileSizes. -//!+walkDir +// !+walkDir func walkDir(dir string, n *sync.WaitGroup, fileSizes chan<- int64) { defer n.Done() for _, entry := range dirents(dir) { @@ -98,7 +97,7 @@ func walkDir(dir string, n *sync.WaitGroup, fileSizes chan<- int64) { //!-walkDir -//!+sema +// !+sema // sema is a counting semaphore for limiting concurrency in dirents. var sema = make(chan struct{}, 20) @@ -109,7 +108,7 @@ func dirents(dir string) []os.FileInfo { // ... //!-sema - entries, err := ioutil.ReadDir(dir) + entries, err := os.ReadDir(dir) if err != nil { fmt.Fprintf(os.Stderr, "du: %v\n", err) return nil diff --git a/lectures/03-goroutines/lecture.slide b/lectures/03-goroutines/lecture.slide index ac52046..aa224c6 100644 --- a/lectures/03-goroutines/lecture.slide +++ b/lectures/03-goroutines/lecture.slide @@ -16,6 +16,10 @@ .play clock1/main.go /func main()/,/^}/ +Для проверки работоспособности можно выполнить в unix-консоли команду: + + nc localhost 8000 + * Clock Handler .play clock1/main.go /func handleConn/,/^}/ diff --git a/lectures/04-testing/gomock/example_test.go b/lectures/04-testing/gomock/example_test.go index 047672a..3015fbd 100644 --- a/lectures/04-testing/gomock/example_test.go +++ b/lectures/04-testing/gomock/example_test.go @@ -9,8 +9,6 @@ import ( func TestFoo(t *testing.T) { ctrl := gomock.NewController(t) - defer ctrl.Finish() // Assert that Bar() is invoked. - m := NewMockFoo(ctrl) // Asserts that the first and only call to Bar() is passed 99. diff --git a/lectures/04-testing/gomock/mock.go b/lectures/04-testing/gomock/mock.go index 244d490..b6d5ac2 100644 --- a/lectures/04-testing/gomock/mock.go +++ b/lectures/04-testing/gomock/mock.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: gitlab.com/manytask/itmo-go/public/lectures/04-testing/gomock (interfaces: Foo) +// Source: gitlab.com/slon/shad-go/lectures/04-testing/gomock (interfaces: Foo) // Package example is a generated GoMock package. package example diff --git a/lectures/04-testing/httptest/main.go b/lectures/04-testing/httptest/main.go index 39afd03..f329863 100644 --- a/lectures/04-testing/httptest/main.go +++ b/lectures/04-testing/httptest/main.go @@ -3,7 +3,6 @@ package main import ( "fmt" "io" - "io/ioutil" "net/http" "net/http/httptest" ) @@ -18,7 +17,7 @@ func main() { handler(w, req) resp := w.Result() - body, _ := ioutil.ReadAll(resp.Body) + body, _ := io.ReadAll(resp.Body) fmt.Println(resp.StatusCode) fmt.Println(resp.Header.Get("Content-Type")) diff --git a/lectures/04-testing/lecture.slide b/lectures/04-testing/lecture.slide index c410b47..061551c 100644 --- a/lectures/04-testing/lecture.slide +++ b/lectures/04-testing/lecture.slide @@ -285,7 +285,7 @@ Good example go test -cover PASS coverage: 42.9% of statements - ok gitlab.com/manytask/itmo-go/public/lectures/04-testing/size 0.001s + ok gitlab.com/slon/shad-go/lectures/04-testing/size 0.001s * Coverage @@ -543,13 +543,13 @@ Good example ================== WARNING: DATA RACE Read at 0x00c000092090 by goroutine 8: - gitlab.com/manytask/itmo-go/public/lectures/04-testing/race.TestRace() + gitlab.com/slon/shad-go/lectures/04-testing/race.TestRace() /home/prime/Code/shad-go/lectures/04-testing/race/race_test.go:25 +0x144 testing.tRunner() /usr/local/go/src/testing/testing.go:909 +0x199 Previous write at 0x00c000092090 by goroutine 9: - gitlab.com/manytask/itmo-go/public/lectures/04-testing/race.TestRace.func1() + gitlab.com/slon/shad-go/lectures/04-testing/race.TestRace.func1() /home/prime/Code/shad-go/lectures/04-testing/race/race_test.go:17 +0x6c ... @@ -557,7 +557,7 @@ Good example --- FAIL: TestRace (0.00s) testing.go:853: race detected during execution of test FAIL - FAIL gitlab.com/manytask/itmo-go/public/lectures/04-testing/race 0.007s + FAIL gitlab.com/slon/shad-go/lectures/04-testing/race 0.007s * White box testing diff --git a/lectures/05-concurrency/context/value/value.go b/lectures/05-concurrency/context/value/value.go new file mode 100644 index 0000000..8c29732 --- /dev/null +++ b/lectures/05-concurrency/context/value/value.go @@ -0,0 +1,32 @@ +package main + +import ( + "context" + "fmt" +) + +type myKey struct{} // use private type to restrict access to this package + +func WithUser(ctx context.Context, user string) context.Context { + return context.WithValue(ctx, myKey{}, user) +} + +// Export type-safe interface for users of this value +func ContextUser(ctx context.Context) (string, bool) { + v := ctx.Value(myKey{}) + s, ok := v.(string) + return s, ok +} + +// OMIT + +func main() { + ctx := context.Background() + + user, ok := ContextUser(ctx) + fmt.Println(ok, user) + + ctx = WithUser(ctx, "petya") + user, ok = ContextUser(ctx) + fmt.Println(ok, user) +} diff --git a/lectures/05-concurrency/lecture.slide b/lectures/05-concurrency/lecture.slide index 533fe50..7166aca 100644 --- a/lectures/05-concurrency/lecture.slide +++ b/lectures/05-concurrency/lecture.slide @@ -179,6 +179,86 @@ Concurrency with Shared Memory x:0 y:0 y:0 x:0 +* Atomics + + var x, y atomic.Int32 + go func() { + x.Store(1) // A1 + fmt.Print("y:", y.Load(), " ") // A2 + }() + go func() { + y.Store(1) // B1 + fmt.Print("x:", x.Load(), " ") // B2 + }() + +In the terminology of the Go memory model, if the effect of an atomic operation A is observed by atomic operation B, then A “synchronizes before” B. + +Additionally, all the atomic operations executed in a program behave as though executed in some sequentially consistent order. + +This definition provides the same semantics as C++'s sequentially consistent atomics and Java's volatile variables. + +* Atomic Int + + type Uint32 struct {} + + // Load atomically loads and returns the value stored in x. + func (x *Uint32) Load() uint32 + + // Store atomically stores val into x. + func (x *Uint32) Store(val uint32) + + // Swap atomically stores new into x and returns the previous value. + func (x *Uint32) Swap(new uint32) (old uint32) + + // CompareAndSwap executes the compare-and-swap operation for x. + func (x *Uint32) CompareAndSwap(old, new uint32) (swapped bool) + + // Add atomically adds delta to x and returns the new value. + func (x *Uint32) Add(delta uint32) (new uint32) + +* Atomic Value + + type Value struct {} + + // Load atomically loads and returns the value stored in x. + func (x *Value) Load() any + + // Store atomically stores val into x. + func (x *Value) Store(val any) + + // Swap atomically stores new into x and returns the previous value. + func (x *Value) Swap(new any) (old any) + + // CompareAndSwap executes the compare-and-swap operation for x. + func (x *Value) CompareAndSwap(old, new any) (swapped bool) + +* Config update + + func main() { + var config atomic.Value // holds current server configuration + // Create initial config value and store into config. + config.Store(loadConfig()) + go func() { + // Reload config every 10 seconds + // and update config value with the new version. + for { + time.Sleep(10 * time.Second) + config.Store(loadConfig()) + } + }() + // Create worker goroutines that handle incoming requests + // using the latest config value. + for i := 0; i < 10; i++ { + go func() { + for r := range requests() { + c := config.Load() + // Handle request r using config c. + _, _ = r, c + } + }() + } + } + * Ленивая инициализация sync.Once. var icons map[string]image.Image @@ -413,3 +493,8 @@ Concurrency with Shared Memory if err != nil { // возможно тут будет DeadlineExceeded } + +* context и передача значений + +.code context/value/value.go /type/,/OMIT/ +.code context/value/value.go /func main/,/}/ diff --git a/lectures/05-modules/lectures.slide b/lectures/05-modules/lectures.slide index eb7cc75..b4e2b2b 100644 --- a/lectures/05-modules/lectures.slide +++ b/lectures/05-modules/lectures.slide @@ -3,368 +3,6 @@ Modules Арсений Балобанов -* Before modules - -* Before modules - -Install go. - - # export PATH=$PATH:$GOROOT/bin - # go version - go version go1.10.8 linux/amd64 - -Create workspace. - - mkdir -p go - export GOPATH=./go - -- *GOROOT* -- where go distribution is installed -- *GOPATH* -- where all go code is stored - -* Before modules - - # go help - Go is a tool for managing Go source code. - - Usage: - go command [arguments] - - The commands are: - build compile packages and dependencies - clean remove object files and cached files - doc show documentation for package or symbol - env print Go environment information - bug start a bug report - fix update packages to use new APIs - fmt gofmt (reformat) package sources - generate generate Go files by processing source - get download and install packages and dependencies - install compile and install packages and dependencies - list list packages - run compile and run Go program - test test packages - tool run specified go tool - version print Go version - vet report likely mistakes in packages - ... - -* Before modules - -Use *go*help*[command]* for more information about a command. - - # go help env - usage: go env [-json] [var ...] - - Env prints Go environment information. - - By default env prints information as a shell script - (on Windows, a batch file). If one or more variable - names is given as arguments, env prints the value of - each named variable on its own line. - - The -json flag prints the environment in JSON format - instead of as a shell script. - - For more about environment variables, see 'go help environment'. - -* Before modules - - # go env - GOARCH="amd64" - GOBIN="" - GOCACHE="/root/.cache/go-build" - GOEXE="" - GOHOSTARCH="amd64" - GOHOSTOS="linux" - GOOS="linux" - GOPATH="/go" - GORACE="" - GOROOT="/usr/local/go" - GOTMPDIR="" - GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64" - GCCGO="gccgo" - CC="gcc" - CXX="g++" - CGO_ENABLED="1" - CGO_CFLAGS="-g -O2" - CGO_CPPFLAGS="" - CGO_CXXFLAGS="-g -O2" - CGO_FFLAGS="-g -O2" - CGO_LDFLAGS="-g -O2" - PKG_CONFIG="pkg-config" - GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -gno-record-gcc-switches" - -* Before modules - -- *GOARCH* -- target compilation architecture, e.g. amd64, arm -- *GOOS* -- target operating system, e.g. linux, darwin, windows - -* Before modules - -- *go*install* -- compiles and installs the packages named by the import paths. - -.link https://github.com/golang/vgo https://github.com/golang/vgo - - # go install golang.org/x/vgo - can't load package: package golang.org/x/vgo: cannot find package "golang.org/x/vgo" in any of: - /usr/local/go/src/golang.org/x/vgo (from $GOROOT) - /go/src/golang.org/x/vgo (from $GOPATH) - -* Before modules - -- *go*get* -- downloads the packages named by the import paths, along with their dependencies. - It then installs the named packages like *go*install*. - - # go get golang.org/x/vgo - # tree -L 4 $GOPATH - /go - |-- bin - | `-- vgo - `-- src - `-- golang.org - `-- x - |-- text - `-- vgo - -- *golang.org/x* -- namespace -- *text*, *vgo* -- projects - -* Before modules - -- *$GOPATH/bin* -- executable files -- *$GOPATH/src* -- source files e.g. .go - -* Before modules - - # mkdir -p src/github.com/verytable/hello - # cat src/github.com/verytable/hello/main.go - package main - - func main() { - fmt.Println("Hello, World!") - } - -- *go*run* compiles and runs the main package comprising the named Go source files. - - # go run src/github.com/verytable/hello/main.go - # command-line-arguments - src/github.com/verytable/hello/main.go:4:2: undefined: fmt - -* Before modules - -Install goimports - - # go get golang.org/x/tools/cmd/goimports - # tree -L 2 $GOPATH - /go - |-- bin - | |-- goimports - | `-- vgo - `-- src - |-- github.com - `-- golang.org - # export PATH=$GOPATH/bin:$PATH - -* Before modules - -Fix imports and format file. - - # goimports -w src/github.com/verytable/hello/main.go - # cat src/github.com/verytable/hello/main.go - package main - - import "fmt" - - func main() { - fmt.Println("Hello, World!") - } - -Compile and run. - - # go run src/github.com/verytable/hello/main.go - Hello, World! - -* Before modules - -- *gofmt* -- gofmt formats Go programs -- *go*fmt* -- runs the command 'gofmt -l -w' -- *goimports* -- updates Go import lines, adding missing ones and removing unreferenced ones; also formats your code - -* Before modules - - # go build github.com/verytable/hello - # ./hello - Hello, World! - -- *go*build* -- compiles the packages named by the import paths along with their dependencies, but it does not install the results. - -* Before modules - - # go install github.com/verytable/hello - # tree -L 2 $GOPATH - /go - |-- bin - | |-- goimports - | |-- hello - | `-- vgo - |-- hello - `-- src - |-- github.com - `-- golang.org - -Run installed binary. - - # $GOPATH/bin/hello - Hello, World! - -- *go*install* -- compiles and installs the packages named by the import paths. - -* Before modules - - # mkdir -p src/github.com/verytable/string - # cat src/github.com/verytable/string/string.go - package string - - func Reverse(s string) string { - b := []byte(s) - for i := 0; i < len(b)/2; i++ { - j := len(b) - i - 1 - b[i], b[j] = b[j], b[i] - } - return string(b) - } - -Compile. - - # go build github.com/verytable/string - # echo $? - 0 - -* Before modules - -Install package - - # go install github.com/verytable/string - # tree -L 2 $GOPATH - /go - |-- bin - | |-- goimports - | |-- hello - | `-- vgo - |-- pkg - | `-- linux_amd64 - `-- src - |-- github.com - `-- golang.org - -- *$GOPATH/pkg* -- compiled libraries e.g. .a - -* Before modules - - # tree -L 4 $GOPATH/pkg - /go/pkg - `-- linux_amd64 - `-- github.com - `-- verytable - `-- string.a - -- *linux_amd64* -- ${GOOS}_${GOARCH} - -* Before modules - -Let's use string package. - - # cat src/github.com/verytable/hello/main.go - package main - - import ( - "fmt" - - "github.com/verytable/string" - ) - - func main() { - fmt.Println(string.Reverse("Hello, World!")) - } - -Install and run. - - # go install github.com/verytable/hello - # hello - !dlroW ,olleH - -* Before modules - -Add dependency. - - # cat src/github.com/verytable/hello/main.go - package main - - import ( - "fmt" - - "github.com/verytable/string" - "rsc.io/sampler" - ) - - func main() { - fmt.Println(string.Reverse("Hello, World!")) - fmt.Println(sampler.Glass()) - } - -Compile and run. - - # go run src/github.com/verytable/hello/main.go - src/github.com/verytable/hello/main.go:7:2: cannot find package "rsc.io/sampler" in any of: - /usr/local/go/src/rsc.io/sampler (from $GOROOT) - /go/src/rsc.io/sampler (from $GOPATH) - -* Before modules - -Download dependencies. - - # go get -v github.com/verytable/hello - Fetching https://rsc.io/sampler?go-get=1 - Parsing meta tags from https://rsc.io/sampler?go-get=1 (status code 200) - get "rsc.io/sampler": found meta tag get.metaImport{Prefix:"rsc.io/sampler", VCS:"git", RepoRoot:"https://github.com/rsc/sampler"} at https://rsc.io/sampler?go-get=1 - rsc.io/sampler (download) - -Compile and run. - - # go run src/github.com/verytable/hello/main.go - !dlroW ,olleH - I can eat glass and it doesn't hurt me. - -* Before modules - -- *go*list* -- lists the packages named by the import paths, one per line. - -List packages. - - # go list github.com/verytable/hello - github.com/verytable/hello - -List package files. - - # go list -f {{.GoFiles}} github.com/verytable/hello - [main.go] - -List package imports. - - # go list -f {{.Imports}} github.com/verytable/hello - [fmt github.com/verytable/string rsc.io/sampler] - -Run 'go help list' to see all format options. - -* Before modules - -- A workspace ($GOPATH) contains many version control repositories (managed by Git, for example). -- Each repository contains one or more packages. -- Each package consists of one or more Go source files in a single directory. -- The path to a package's directory determines its import path. - -* Modules - * Modules # go mod init github.com/verytable/hello @@ -372,18 +10,19 @@ Run 'go help list' to see all format options. # cat go.mod module github.com/verytable/hello - go 1.16 + go 1.22.0 -- *package* -- collection of source files in the same directory that are compiled together -- *module* -- collection of related Go packages that are released together -- github.com/verytable/hello -- *module*path*, the import path prefix for all packages within the module +- *package* — набор исходных файлов из одной директории, которые компилируются вместе +- *module* — набор пакетов, которые релизятся вместе +- github.com/verytable/hello — *module*path*, префикс всех пакетов модуля * Modules -- *import*path* -- string used to import a package +- *import*path* — строчка для импорта пакета -For example, the module `github.com/google/go-cmp` contains a package in the directory `cmp/`. -That package's import path is `github.com/google/go-cmp/cmp`. +Например, в модуле `github.com/google/go-cmp` есть директория `cmp/`. + +import path пакета `cmp` будет `github.com/google/go-cmp/cmp`. * Modules @@ -404,17 +43,6 @@ Install binary. Hello, world! # go env -u GOBIN -* Modules - - # git init - Initialized empty Git repository in /tmp/hello/.git/ - # git add hello.go go.mod - # git commit -m "initial commit" - [master (root-commit) f22a6c1] initial commit - 2 files changed, 10 insertions(+) - create mode 100644 go.mod - create mode 100644 hello.go - * Modules # mkdir -p morestrings @@ -428,22 +56,20 @@ Install binary. } return string(r) } - # go build ./morestrings - * Modules -Check build. + # go build ./morestrings // в репозитории ничего не изменится - # go build ./morestrings +- *go*env*GOCACHE* — внутренний кэш `go`build` -- *GOCACHE* -- 'go build' internal cache location. +Команда go кэширует выходные данные сборки для повторного использования в будущих сборках. -go command caches build outputs for reuse in future builds. Run 'go help cache' for more info. +`go`help`cache` для деталей. * Modules -Use subpackage. +Используем subpackage # cat hello.go package main @@ -457,13 +83,14 @@ Use subpackage. func main() { fmt.Println(morestrings.ReverseRunes("!oG ,olleH")) } + # go install github.com/verytable/hello # hello Hello, Go! * Modules -Add external dependency. +Добавляем внешнюю зависимость # cat hello.go package main @@ -484,8 +111,7 @@ Add external dependency. # go mod tidy go: finding module for package github.com/google/go-cmp/cmp - go: downloading github.com/google/go-cmp v0.5.5 - go: found github.com/google/go-cmp/cmp in github.com/google/go-cmp v0.5.5 + go: found github.com/google/go-cmp/cmp in github.com/google/go-cmp v0.6.0 # go install # hello Hello, Go! @@ -494,48 +120,68 @@ Add external dependency. +  "Hello Go",   ) -Requirements are stored in go.mod. +Внешние зависимости хранятся in go.mod. # cat go.mod module github.com/verytable/hello - go 1.16 + go 1.22.0 - require github.com/google/go-cmp v0.5.5 + require github.com/google/go-cmp v0.6.0 * Modules - *go*mod*tidy* makes sure go.mod matches the source code in the module -Run 'go mod help tidy' for details. +`go`mod`help`tidy` для подробностей. * Modules -Modules are downloaded to *$GOPATH/pkg/mod*. +Исходный код модулей хранится в *$GOPATH/pkg/mod*. # tree -L 2 $GOPATH/pkg/mod/github.com/google ... - ├── go-cmp@v0.4.0 + ├── go-cmp@v0.5.9 │   ├── cmp │   ├── CONTRIBUTING.md │   ├── go.mod - │   ├── go.sum │   ├── LICENSE │   └── README.md - ├── go-cmp@v0.5.5 + ├── go-cmp@v0.6.0 │   ├── cmp │   ├── CONTRIBUTING.md │   ├── go.mod - │   ├── go.sum │   ├── LICENSE │   └── README.md ... * Modules -- *go*clean* -- removes object files from package source directories +- *go*clean* — чистит системные директории -Run 'go clean -modcache' to remove all downloaded modules. +`go`clean`-modcache` удаляет *все* модули из *$GOPATH/pkg/mod*. + +`go`clean`-cache` удаляет объекты из *GOCACHE*. + +* Modules + +Установить другую версию пакета. + + # go get github.com/google/go-cmp/cmp@v0.5.5 + go: downloading github.com/google/go-cmp v0.5.5 + go: downgraded github.com/google/go-cmp v0.6.0 => v0.5.5 + +Обновить модули. + + # go mod tidy + go: downloading golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 + + # cat go.mod + module github.com/verytable/hello + + go 1.22.0 + + require github.com/google/go-cmp v0.5.5 * Modules @@ -562,11 +208,9 @@ Format options. Error *ModuleError // error loading module } - - * Modules -- *go.sum* -- stores the expected cryptographic hashes of the content of specific module versions +- *go.sum* — хранит хэши модулей # cat go.sum github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= @@ -576,17 +220,19 @@ Format options. * Modules -- *go*mod*graph* prints the module requirement graph +- *go*mod*graph* — печатает граф зависимостей модулей # go mod graph github.com/verytable/hello github.com/google/go-cmp@v0.5.5 + github.com/verytable/hello go@1.22.0 github.com/google/go-cmp@v0.5.5 golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543 + go@1.22.0 toolchain@go1.22.0 * Modules -- *go*mod*why* shows a shortest path in the import graph from the main module to the package +- *go*mod*why* — показывает кратчайший по импортам путь до пакета - # go mod why golang.org/x/xerrors + # go mod why golang.org/x/xerrors # golang.org/x/xerrors github.com/verytable/hello github.com/google/go-cmp/cmp @@ -596,7 +242,7 @@ Format options. * Modules -- *go*mod*vendor* -- copies module requirements to ./vendor directory +- *go*mod*vendor* — копирует зависимости модуля в директорию `./vendor` Vendor dependencies. @@ -619,42 +265,217 @@ Vendor dependencies. github.com/google/go-cmp/cmp/internal/function github.com/google/go-cmp/cmp/internal/value +* Modules + +Indirect зависимости + + # go mod init github.com/verytable/world + go: creating new go.mod: module github.com/verytable/world + + # cat sum.go + package world + + import _ "github.com/jackc/pgx/v5" + + func Sum(a, b int) int { + return a + b + } * Modules -- *GO111MODULE* controls how Go imports packages. on, off or auto. - -*Go*1.11* - -- *on* will force using Go modules even if the project is in your GOPATH. Requires go.mod to work. -- *off* forces Go to behave the GOPATH way, even outside of GOPATH. -- *auto* (default). In this mode, Go will behave - similarly to *on* when you are outside of GOPATH, - similarly to *off* when you are inside the GOPATH even if a go.mod is present. +Indirect зависимости + # go mod tidy + ... + + # cat go.mod + module github.com/verytable/world + + go 1.22.0 + + require github.com/jackc/pgx/v5 v5.5.5 + + require ( + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + ) * Modules -*Go*1.13* +Как импортировать пакет из локального модуля -*GO111MODULE=auto* + # cat hello.go + package main + + import ( + "fmt" -- *on* anywhere there is a go.mod OR anywhere outside the GOPATH even if there is no go.mod. -- *off* in the GOPATH with no go.mod. + "github.com/google/go-cmp/cmp" + "github.com/verytable/hello/morestrings" + "github.com/verytable/world" + ) + + func main() { + fmt.Println(morestrings.ReverseRunes("!oG ,olleH")) + fmt.Println(cmp.Diff("Hello World", "Hello Go")) + + fmt.Println(world.Sum(1, 2)) + } * Modules -*Go*1.16* +Как импортировать пакет из локального модуля + + # go install . + main.go:8:2: no required module provides package github.com/verytable/world; to add it: + go get github.com/verytable/world + + # go get github.com/verytable/world + go: module github.com/verytable/world: git ls-remote -q origin in /home/verytable/go/pkg/mod/cache/vcs/8d15fd58d5b540d58dc97582a5a11fe29782f4416e9628e0183c4ea4f8c7cdcd: exit status 128: + fatal: could not read Username for 'https://github.com': terminal prompts disabled + Confirm the import path was entered correctly. -*on* is a default. +* Modules -- *auto* could be used for previous previous behaviour +- *go*mod*edit* — вносит правки в go.mod -*Go*1.17* + # go mod edit -replace github.com/verytable/world=/tmp/world + # cat go.mod + module github.com/verytable/hello -*GO111MODULE* is will be ignored. + go 1.22.0 + + require github.com/google/go-cmp v0.5.5 + + replace github.com/verytable/world => /tmp/world + +* Modules + + # go get ./... + go: added github.com/jackc/pgpassfile v1.0.0 + go: added github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a + go: added github.com/jackc/pgx/v5 v5.5.5 + go: added github.com/verytable/world v0.0.0-00010101000000-000000000000 + go: added golang.org/x/crypto v0.17.0 + go: added golang.org/x/text v0.14.0 + + # go run . + Hello, Go! + string( + - "Hello World", + + "Hello Go", + ) + + 3 + +* Modules + +Выложить свой пакет в открытый доступ. + + # git init + # git add . + # git commit + # git push + # go get github.com/verytable/hello@v0.0.0-20240303255101-161cd47e91fd + + # git tag v0.0.1 + # git push v0.0.1 + # go get github.com/verytable/hello@v0.0.1 + +* Modules + +Semantic versioning + +.image versions.png _ 700 + +* Modules + +v2 and beyond + +.link https://github.com/googleapis/gax-go Отдельная директория + + ├── go.mod + ├── package.go + └── v2 + ├── go.mod + └── package.go + +.link https://github.com/go-yaml/yaml Git ветки + + main == v0/v1 + ├── go.mod + └── package.go + + v2 == v2 + ├── go.mod + └── package.go + +* Modules + +Module proxy + + # curl https://proxy.golang.org/github.com/google/go-cmp/@v/list + v0.5.8 + v0.5.5 + v0.6.0 + + # curl https://proxy.golang.org/github.com/google/go-cmp/@v/v0.5.5.info + {"Version":"v0.5.5","Time":"2021-03-03T20:48:37Z"} + + # curl https://proxy.golang.org/github.com/google/go-cmp/@latest + {"Version":"v0.6.0", + "Time":"2023-08-31T17:32:40Z", + "Origin":{"VCS":"git","URL":"https://github.com/google/go-cmp","Ref":"refs/tags/v0.6.0", ...}} + + # curl https://proxy.golang.org/github.com/google/go-cmp/@v/v0.6.0.mod + module github.com/google/go-cmp + + go 1.13 + + # curl -O https://proxy.golang.org/github.com/google/go-cmp/@v/v0.6.0.zip + +* Modules + +Module proxy + + # go get -x github.com/google/go-cmp/cmp + get https://proxy.golang.org/github.com/@v/list + get https://proxy.golang.org/github.com/google/go-cmp/@v/list + get https://proxy.golang.org/github.com/google/go-cmp/cmp/@v/list + get https://proxy.golang.org/github.com/google/@v/list + get https://proxy.golang.org/github.com/google/go-cmp/cmp/@v/list: 404 Not Found (0.622s) + get https://proxy.golang.org/github.com/google/@v/list: 404 Not Found (0.622s) + get https://proxy.golang.org/github.com/@v/list: 404 Not Found (0.622s) + get https://proxy.golang.org/github.com/google/go-cmp/@v/list: 200 OK (0.638s) + go: added github.com/google/go-cmp v0.6.0 + +* Modules + +Vanity import + +Исходный код лежит на [[https://github.com/uber-go/atomic][https://github.com/uber-go/atomic]], однако импорт другой + + import "go.uber.org/atomic" + +Команда *go*get* внутри делает http запрос к [[https://go.uber.org]] + + # curl https://go.uber.org/atomic\?go-get\=1 + + + + + + + + + Nothing to see here. Please move along. + + * Ссылки: -.link https://golang.org/cmd/go/ - go cmd -.link https://play-with-go.dev/ - play-with-go +.link https://golang.org/cmd/go/ — go cmd +.link https://www.youtube.com/watch?v=F8nrpe0XWRg — ▶️ Go with Versions, Russ Cox +.link https://play-with-go.dev/ — play-with-go diff --git a/lectures/05-modules/versions.png b/lectures/05-modules/versions.png new file mode 100644 index 0000000..3d6c837 Binary files /dev/null and b/lectures/05-modules/versions.png differ diff --git a/lectures/06-http/httptest/code.go b/lectures/06-http/httptest/code.go index 0198526..e929bdb 100644 --- a/lectures/06-http/httptest/code.go +++ b/lectures/06-http/httptest/code.go @@ -2,7 +2,7 @@ package httptest import ( "context" - "io/ioutil" + "io" "net/http" "strconv" ) @@ -31,7 +31,7 @@ func (c *APIClient) GetReposCount(ctx context.Context, userID string) (int, erro return 0, err } defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return 0, err } diff --git a/lectures/06-http/keepalive/correct/correct.go b/lectures/06-http/keepalive/correct/correct.go index dc919a9..e497238 100644 --- a/lectures/06-http/keepalive/correct/correct.go +++ b/lectures/06-http/keepalive/correct/correct.go @@ -3,7 +3,6 @@ package main import ( "fmt" "io" - "io/ioutil" "net/http" "sync" ) @@ -25,7 +24,7 @@ func main() { return } defer resp.Body.Close() - _, _ = io.Copy(ioutil.Discard, resp.Body) + _, _ = io.Copy(io.Discard, resp.Body) fmt.Printf("%s - %d\n", url, resp.StatusCode) }(url) } diff --git a/lectures/07-distbuild/bazel.svg b/lectures/07-distbuild/bazel.svg new file mode 100644 index 0000000..2bffd02 --- /dev/null +++ b/lectures/07-distbuild/bazel.svg @@ -0,0 +1,151 @@ + + + + + + +mygraph + + + +//absl/random:random + +//absl/random:random + + + +//absl/random:distributions + +//absl/random:distributions + + + +//absl/random:random->//absl/random:distributions + + + + + +//absl/random:seed_sequences + +//absl/random:seed_sequences + + + +//absl/random:random->//absl/random:seed_sequences + + + + + +//absl/random/internal:pool_urbg + +//absl/random/internal:pool_urbg + + + +//absl/random:random->//absl/random/internal:pool_urbg + + + + + +//absl/random/internal:nonsecure_base + +//absl/random/internal:nonsecure_base + + + +//absl/random:random->//absl/random/internal:nonsecure_base + + + + + +//absl/strings:strings + +//absl/strings:strings + + + +//absl/random:distributions->//absl/strings:strings + + + + + +//absl/random:seed_sequences->//absl/random/internal:pool_urbg + + + + + +//absl/random:seed_sequences->//absl/random/internal:nonsecure_base + + + + + +//absl/random/internal:seed_material + +//absl/random/internal:seed_material + + + +//absl/random:seed_sequences->//absl/random/internal:seed_material + + + + + +//absl/random/internal:salted_seed_seq + +//absl/random/internal:salted_seed_seq + + + +//absl/random:seed_sequences->//absl/random/internal:salted_seed_seq + + + + + +//absl/random/internal:pool_urbg->//absl/random/internal:seed_material + + + + + +//absl/random/internal:nonsecure_base->//absl/random/internal:pool_urbg + + + + + +//absl/random/internal:nonsecure_base->//absl/random/internal:seed_material + + + + + +//absl/random/internal:nonsecure_base->//absl/random/internal:salted_seed_seq + + + + + +//absl/random/internal:seed_material->//absl/strings:strings + + + + + +//absl/random/internal:salted_seed_seq->//absl/random/internal:seed_material + + + + + diff --git a/lectures/07-distbuild/graph.avif b/lectures/07-distbuild/graph.avif new file mode 100644 index 0000000..be38b7e Binary files /dev/null and b/lectures/07-distbuild/graph.avif differ diff --git a/lectures/07-distbuild/hash.avif b/lectures/07-distbuild/hash.avif new file mode 100644 index 0000000..34f5568 Binary files /dev/null and b/lectures/07-distbuild/hash.avif differ diff --git a/lectures/07-distbuild/jobs.avif b/lectures/07-distbuild/jobs.avif new file mode 100644 index 0000000..2b8ff32 Binary files /dev/null and b/lectures/07-distbuild/jobs.avif differ diff --git a/lectures/07-distbuild/lecture.slide b/lectures/07-distbuild/lecture.slide new file mode 100644 index 0000000..ea2a1c2 --- /dev/null +++ b/lectures/07-distbuild/lecture.slide @@ -0,0 +1,82 @@ +# distbuild +Домашнее задание 2 + +## Цели второго ДЗ + +- Написать _сложную_ систему + - Без _сложных_ алгоритмов + - Но с большим числом движущихся частей + +- Написать подсистему исполнения джобов + +- Написать клиент + сервер + +## Современная сборка + +Что происходит, когда вы запускаете `go build ./cmd/gitfame`? + +.image graph.avif _ 900 + +## Современная сборка + +Что происходит, когда вы запускаете `go build ./cmd/gitfame`? + +1. `go build` строит граф сборки + - Вершина графа - файл + команда для его сборки (compile/link) + - Ребра - входные файлы для команды / зависимости + - Чтобы слинковать исполняемый файл, нужно скомпилировать все пакеты + - Чтобы запустить тест, нужно собрать исполняемый файл теста + - Все зависимости явно указаны в графе (герметичность). `./run-whatever.sh` +2. Граф сборки исполняется + - Команды в вершинах исполняются параллельно, если это возможно + - Результаты складываются в кэш + - Вместо исполнения команды, результат могут взять из кеша + +## Современная сборка + +.image jobs.avif _ 900 + +## Как работает кэш + +Обычный кэш `key -> value`. + +- `value` - директория с файлами +- Как сформировать ключ? + - `"./cmd/gitfame"` - не подходит + - Можно использовать хеш `sha1` от всех входных файлов и от всех команд вершины. + - Хеш входного файла можно заменить на ключ вершины, которая его породила. + +## Как работает кэш + +.image hash.avif _ 900 + +## Задача distbuild + +- Граф сборки дан на вход +- Нужно исполнить этот граф в распределённой системе и закешировать результат + +- Система состоит из 3-х компонент: + * Клиент + * Координатор + * Воркер + +## Клиент + +* Представьте, что он работает внутри команды `go build` +* Вам дают граф сборки. +* Нужно залить граф на координатор, вместе с исходными файлами. +* После этого, стримить результаты исполнения с координатора. + +## Воркер + +* В цикле просит с координатора следующий джоб и исполняет его. +* Хранит кеш артефактов. + +## Координатор + +* Общается с клиентом и воркером. +* Решает на каком воркере запускать какой джоб. + +## Links + +- [How bazel works](https://sluongng.hashnode.dev/bazel-caching-explained-pt-1-how-bazel-works) diff --git a/lectures/07-sql/alive/ping.go b/lectures/07-sql/alive/ping.go index e7ffded..a12c2cc 100644 --- a/lectures/07-sql/alive/ping.go +++ b/lectures/07-sql/alive/ping.go @@ -5,7 +5,7 @@ import ( "database/sql" "log" - _ "github.com/jackc/pgx/v4/stdlib" + _ "github.com/jackc/pgx/v5/stdlib" ) func IsItAliveQuestionMark(ctx context.Context) { diff --git a/lectures/07-sql/hasql/open.go b/lectures/07-sql/hasql/open.go index bdc1e51..63f49ad 100644 --- a/lectures/07-sql/hasql/open.go +++ b/lectures/07-sql/hasql/open.go @@ -6,7 +6,7 @@ import ( "log" "time" - _ "github.com/jackc/pgx/v4/stdlib" + _ "github.com/jackc/pgx/v5/stdlib" "golang.yandex/hasql" "golang.yandex/hasql/checkers" ) diff --git a/lectures/07-sql/open/pgx.go b/lectures/07-sql/open/pgx.go index b71557b..0282c07 100644 --- a/lectures/07-sql/open/pgx.go +++ b/lectures/07-sql/open/pgx.go @@ -4,7 +4,7 @@ import ( "context" "log" - "github.com/jackc/pgx/v4" + "github.com/jackc/pgx/v5" ) func PGXOpen() { diff --git a/lectures/07-sql/open/sql.go b/lectures/07-sql/open/sql.go index 94ff648..46fe4c7 100644 --- a/lectures/07-sql/open/sql.go +++ b/lectures/07-sql/open/sql.go @@ -4,7 +4,7 @@ import ( "database/sql" "log" - _ "github.com/jackc/pgx/v4/stdlib" + _ "github.com/jackc/pgx/v5/stdlib" ) func SQLOpen() { diff --git a/lectures/07-sql/sqlx/open.go b/lectures/07-sql/sqlx/open.go index 0d701ff..3210fd4 100644 --- a/lectures/07-sql/sqlx/open.go +++ b/lectures/07-sql/sqlx/open.go @@ -3,7 +3,7 @@ package sqlx import ( "log" - _ "github.com/jackc/pgx/v4/stdlib" + _ "github.com/jackc/pgx/v5/stdlib" "github.com/jmoiron/sqlx" ) diff --git a/lectures/08-generics/lecture.slide b/lectures/08-generics/lecture.slide index 5273f41..d2de014 100644 --- a/lectures/08-generics/lecture.slide +++ b/lectures/08-generics/lecture.slide @@ -433,7 +433,7 @@ but why not just P.S. are these functions equivalent? -- Type parameter be replaced by simple interface +- Type parameter can be replaced by simple interface * When not to use generics diff --git a/lectures/11-runtime/.gdb_history b/lectures/11-runtime/.gdb_history deleted file mode 100644 index fc5962c..0000000 --- a/lectures/11-runtime/.gdb_history +++ /dev/null @@ -1 +0,0 @@ -bt diff --git a/lectures/11-runtime/bce/main.go b/lectures/11-runtime/bce/main.go new file mode 100644 index 0000000..5320fd4 --- /dev/null +++ b/lectures/11-runtime/bce/main.go @@ -0,0 +1,15 @@ +package main + +import "encoding/binary" + +func main() { + d := make([]byte, 16) + + // if 10 < len(d) { + // panic("out of bound") + // } + d[10] = 12 + + i := binary.LittleEndian.Uint64(d) + _ = i +} diff --git a/lectures/11-runtime/escape/main.go b/lectures/11-runtime/escape/main.go new file mode 100644 index 0000000..8eef87d --- /dev/null +++ b/lectures/11-runtime/escape/main.go @@ -0,0 +1,14 @@ +package main + +var g any + +func main() { + p0 := make([]byte, 10) + p0[0] = 'f' + + var p1 [10]byte + + copy(p1[:], p0) + + g = p1 +} diff --git a/lectures/11-runtime/gc/main.go b/lectures/11-runtime/gc/main.go new file mode 100644 index 0000000..7c07df1 --- /dev/null +++ b/lectures/11-runtime/gc/main.go @@ -0,0 +1,47 @@ +package main + +import ( + "fmt" + "os" + "runtime" + "time" +) + +func finalizers() { + f, err := os.Open("x.txt") + + select {} + + _ = f.Close() + + _, _ = f, err +} + +type myX struct{} + +func (xx *myX) close() { + fmt.Println("finalized") + + runtime.SetFinalizer(xx, (*myX).close) +} + +var g any + +func finalizersMy() { + xx := new(myX) + + runtime.SetFinalizer(xx, (*myX).close) + + for { + g = make([]byte, 1<<20) + + time.Sleep(time.Second) + + xx = nil + runtime.GC() + } +} + +func main() { + finalizersMy() +} diff --git a/lectures/11-runtime/gmp.png b/lectures/11-runtime/gmp.png new file mode 100644 index 0000000..2203a34 Binary files /dev/null and b/lectures/11-runtime/gmp.png differ diff --git a/lectures/11-runtime/inline/main.go b/lectures/11-runtime/inline/main.go new file mode 100644 index 0000000..604699e --- /dev/null +++ b/lectures/11-runtime/inline/main.go @@ -0,0 +1,13 @@ +package main + +import ( + "os" +) + +func F(a int) int { + return 2 / (a - 1) +} + +func main() { + os.Exit(F(len(os.Args))) +} diff --git a/lectures/11-runtime/lecture.slide b/lectures/11-runtime/lecture.slide index 237208a..405a20d 100644 --- a/lectures/11-runtime/lecture.slide +++ b/lectures/11-runtime/lecture.slide @@ -19,17 +19,31 @@ Go Runtime Internals * GC - Finalizer -- Knobs +- Knobs `GOGC` - sync.Pool - STW - Mark Assist -- Stack Growth - Write Barrier +- Stack Growth * Scheduler - G, M, P model - Global Run Queue, Local Run Queue -- Knobs -- Runaway threads problem +- Knobs `GOMAXPROCS` +- cgo & system call - runtime.LockOsThread + +* runtime + +- stacktraces +- mem stats +- runtime/debug +- gc stats + +* Tools + +- delve +- gdb +- runtime/pprof +- net/http/pprof diff --git a/lectures/11-runtime/pool/main.go b/lectures/11-runtime/pool/main.go new file mode 100644 index 0000000..590826b --- /dev/null +++ b/lectures/11-runtime/pool/main.go @@ -0,0 +1,32 @@ +package main + +import ( + "net/http" + "sync" +) + +var pool = sync.Pool{ + New: func() any { + return &Decoder{} + }, +} + +type Decoder struct { + buf [1 << 20]byte +} + +func New() *Decoder { + return pool.Get().(*Decoder) +} + +func (c *Decoder) Close() { + pool.Put(c) +} + +func main() { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + d := New() + + d.Close() + }) +} diff --git a/lectures/11-runtime/pprof/main.go b/lectures/11-runtime/pprof/main.go new file mode 100644 index 0000000..d426da1 --- /dev/null +++ b/lectures/11-runtime/pprof/main.go @@ -0,0 +1,16 @@ +package main + +import ( + "net/http" + _ "net/http/pprof" +) + +func main() { + for i := 0; i < 10000; i++ { + go func() { + select {} + }() + } + + http.ListenAndServe(":8080", nil) +} diff --git a/lectures/11-runtime/unsafe/main.go b/lectures/11-runtime/unsafe/main.go new file mode 100644 index 0000000..f9342c4 --- /dev/null +++ b/lectures/11-runtime/unsafe/main.go @@ -0,0 +1,21 @@ +package main + +import "unsafe" + +const x = unsafe.Sizeof(int(0)) + +type y [x]int + +type s struct { + a bool + b int16 + c []int +} + +const z = unsafe.Offsetof(s{}.b) + +func main() { + _ = x + + var _ y +} diff --git a/lectures/12-observability/jaeger.png b/lectures/12-observability/jaeger.png new file mode 100644 index 0000000..cc5d6e9 Binary files /dev/null and b/lectures/12-observability/jaeger.png differ diff --git a/lectures/12-observability/lecture.slide b/lectures/12-observability/lecture.slide new file mode 100644 index 0000000..4952ceb --- /dev/null +++ b/lectures/12-observability/lecture.slide @@ -0,0 +1,159 @@ +# Observability + +Короткий Фёдор + +## Prometheus Data Model + +* Data Model + +``` +http_requests_total +{