
Vany
12.01.2018
13:37:14
а как ты обращаясь к переменной в скупе плучаешь доступ к верхней переменной? она же переопределена через := или нет?

Александр
12.01.2018
13:37:45
да легко, она же выше объявлена
но я копипастил и не заметил := вместо =

Kirill
12.01.2018
13:38:51
Господа, прошу помощи и совета.
Запускаю приложение на го с базой через docker-compose, приложение не может зарезолвить адрес контейнера по его имени, хотя если зайти в контейнер и сделать пинг по имени - все нормально резолвится.
Пробовал переменные окружения
ENV GODEBUG=netdns=go и
ENV GODEBUG=netdns=cgo
- все равно не хочет резолвить имя контейнера с базой. Как быть?

Google

Александр
12.01.2018
13:39:07

Aleksandr
12.01.2018
13:39:26

Александр
12.01.2018
13:39:34
как вы можете заметить, мы нихрена не обработали err и возращаем его

Kirill
12.01.2018
13:39:51
docker-compose в студию
version: '3'
services:
database:
container_name: am-log-user-service-db
image: percona:5.7
environment:
MYSQL_ROOT_PASSWORD: "qazxsw"
MYSQL_DATABASE: am_log_user_service
volumes:
- /opt/DB/am-log-user-service/:/var/lib/mysql/
restart: always
depends_on:
- web
web:
container_name: am-log-user-service-http
image: am-log-user-service
volumes:
- ./log/:/app/log/
ports:
- 8091:8091
restart: on-failure

Александр
12.01.2018
13:40:03
случайно написал := и мы получим чертичто

Aleksandr
12.01.2018
13:40:26
какой хост используешь?

Kirill
12.01.2018
13:41:01

Aleksandr
12.01.2018
13:41:25

Kirill
12.01.2018
13:41:41
Так внутри контейнера нормально резолвится database
Ща попробую сначала композ поправить

Aleksandr
12.01.2018
13:41:56

Kirill
12.01.2018
13:42:08
Тогда я не понял вопроса

Google

Aleksandr
12.01.2018
13:42:21

Kirill
12.01.2018
13:42:28
Нет, сейчас попробую

Aleksandr
12.01.2018
13:42:45
ошибку пишет какую-нибудь?

Kirill
12.01.2018
13:43:06
dial tcp 172.18.0.2:3306: getsockopt: connection refused

Aleksandr
12.01.2018
13:43:38
так может база не стартовала?

Kirill
12.01.2018
13:44:10
Сам контейнер стартовал, базу не проверял

Vany
12.01.2018
13:44:16
Ну так это не неможет разрезолвить ...

Aleksandr
12.01.2018
13:44:44

Vany
12.01.2018
13:44:50
Это значит я туда сходила, там на 3306 никто не слушает

Kirill
12.01.2018
13:44:57
Да, именно

Vany
12.01.2018
13:45:12
причём сам ip существует

Aleksandr
12.01.2018
13:45:17
Да, именно
приложение поднмиается сразу,Э а база через пару секунд. щас код дам

Vany
12.01.2018
13:45:23
тоесть контейнер поднят.

Aleksandr
12.01.2018
13:45:40
Да, именно
db, err := sql.Open("postgres", fmt.Sprintf("postgres://postgres:%s@%s/postgres?sslmode=disable", os.Getenv("POSTGRES_PASSWORD"), os.Getenv("POSTGRES_HOST")))
if err != nil {
log.Fatal(err)
}
for i := 0; i < 10; i++ {
err = db.Ping()
if err == nil {
break
}
log.Print(err)
time.Sleep(2 * time.Second)
}
if err != nil {
log.Fatal(err)
}
типа такого
смысл понятен - пингует, пока база не поднимется

Kirill
12.01.2018
13:46:15
Эмм
А docker-compose при указании depends_on разве не гарантирует, что контейнер с базой поднимется до того как начнет подниматься контейнер с приложением?

Vany
12.01.2018
13:47:00

Aleksandr
12.01.2018
13:47:17

Google

Aleksandr
12.01.2018
13:47:43

Александр
12.01.2018
13:47:58

Vany
12.01.2018
13:48:13
хороший
Просто ты откладываешь свой старт... докер сам не умеет зависить от живости сервиса?

Aleksandr
12.01.2018
13:48:14

Александр
12.01.2018
13:48:26
при старте аппки например
если они поднимают базу, потом аппку
не правильно ждать в аппке пока база поднимается

Aleksandr
12.01.2018
13:49:07

Kirill
12.01.2018
13:49:18
Ну что-то юзкейс слишком частый, я почти на 100% уверен что в композе это по-другому решается

Александр
12.01.2018
13:49:23
а это не забота аппки ?

Kirill
12.01.2018
13:49:29
Вот да

Aleksandr
12.01.2018
13:49:30

Александр
12.01.2018
13:49:36
аппка стартанула не на готовой базе? падаем!

Aleksandr
12.01.2018
13:49:47
depends_on will not wait for db and redis to be “ready” before starting web - only until they have been started. If you need to wait for a service to be ready, see Controlling startup order for more on this problem and strategies for solving it.


Никита
12.01.2018
14:19:25
Если компоуз версии 2 то твое спасение это healthcheck
В ином случае добавляй маленький энтрипоинт который пингует 3 раза (условно) коннекшн и падает если не получилось

Google

Kirill
12.01.2018
14:22:49
Ну у меня энтрипоинт это запуск самого приложения, буду проверять, если нет - падать

Никита
12.01.2018
14:42:23
https://docs.docker.com/compose/compose-file/compose-file-v2/#depends_on
в частности
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
в свою очередь service_healthy базируется на этом https://docs.docker.com/compose/compose-file/compose-file-v2/#healthcheck

Kirill
12.01.2018
14:42:40

Aleksandr
12.01.2018
14:43:57
при работе твой апп должен упасть и докер его должен поднять

Kirill
12.01.2018
14:44:19
Упадет демон базы\контейнер

Aleksandr
12.01.2018
14:44:47

Kirill
12.01.2018
14:44:52
Т.е. апп тоже должен падать? У меня оно юзает в основном локальный кеш и поэтому продолжает жить даже без базы

Admin
ERROR: S client not available

Kirill
12.01.2018
14:45:01
Его же тоже по идее надо обрабатывать, так?

Aleksandr
12.01.2018
14:45:43

Никита
12.01.2018
14:45:51
да, с третьим компоузом грустненько(

Kirill
12.01.2018
14:46:08

Aleksandr
12.01.2018
14:46:24
падаю только если при запуске аппа нету базы через дцать секунд

Kirill
12.01.2018
14:49:56
Посмотрел сервисы других чуваков у себя на работе, нашел такой код:
func (a *Layer) GetDb() *sql.DB {
if a.db != nil {
a.db.Ping()
return a.db
}
db, err := sql.Open("mysql", a.dbCredential.GetConnectionString())
if err != nil {
panic(err)
}
a.db = db
return db
}
И в хттп-хендлерах дергается getDb() а потом через полученный объект делается запрос

Google

Kirill
12.01.2018
14:54:10
Вроде выглядит как хорошая практика
Юзает кто-нибудь такое?
И, если нет предварительной загрузки чего-либо из базы - то и несколько попыток коннекта на старте сервиса можно не делать
Т.к. все по запросу

Aleksandr
12.01.2018
15:00:14
пинговать на каждый getDB - не очень как по мне, а учитывая что там паника дальше, то это то же самое что и у тебя


Aleksey
12.01.2018
15:02:21
Всем привет!
Можете подсказать, создаю структуру с fluent api, которая на каждый вызов возвращает саму себя. Внутри каждый шаг записывается в очередь, которая будет исопльзоваться в последнем вызове.
То есть, вот структура:
type FluentStruct struct {
queue []func(string) string
}
У нее есть статический метод создания
func NewFluentStruct() FluentStruct {
return FluentStruct{}
}
Интерфейс должен быть:
result := NewFluentStruct().Step1().Step2().GetResult()
Проблема в реализации самих степов, хочется, чтобы они расширяли массив изначального экземпляра в виде:
func (f *FluentStruct) Step1() FluentStruct {
f.queue := append(f.queue, smth)
return *f
}
Но в таком случае указанный выше интерфейс не работает и возвращает ошибку
cannot call pointer method on packet.NewFluentStrtuct()
так как этот вызов не создает ссылку, а в методе Step1 я хочу работать именно с ссылкой, чтобы изменять значение поля структуры.
Выхода здесь 2:
1) Создавать ссылку отдельно, а затем прикручивать сами стэпы (Он не подходит, так как нужен именно inline синтаксис):
fluentStruct := NewFluentStruct()
result := fluentStruct.Step1().Step2().GetResult()
2) Переработать метод Step1, чтобы он не модифицировал предыдущий объект, а возвращал новый, то есть получается иммутабельная версия - вариант приемлимый, но я боюсь не будет ли он более затратный по памяти:
func (f FluentStruct) Step1() FluentStruct {
return FluentStruct{append(f.queue, smth)}
}
Заранее спасибо за помощь!


Kirill
12.01.2018
15:12:39


Aleksandr
12.01.2018
15:13:13
Всем привет!
Можете подсказать, создаю структуру с fluent api, которая на каждый вызов возвращает саму себя. Внутри каждый шаг записывается в очередь, которая будет исопльзоваться в последнем вызове.
То есть, вот структура:
type FluentStruct struct {
queue []func(string) string
}
У нее есть статический метод создания
func NewFluentStruct() FluentStruct {
return FluentStruct{}
}
Интерфейс должен быть:
result := NewFluentStruct().Step1().Step2().GetResult()
Проблема в реализации самих степов, хочется, чтобы они расширяли массив изначального экземпляра в виде:
func (f *FluentStruct) Step1() FluentStruct {
f.queue := append(f.queue, smth)
return *f
}
Но в таком случае указанный выше интерфейс не работает и возвращает ошибку
cannot call pointer method on packet.NewFluentStrtuct()
так как этот вызов не создает ссылку, а в методе Step1 я хочу работать именно с ссылкой, чтобы изменять значение поля структуры.
Выхода здесь 2:
1) Создавать ссылку отдельно, а затем прикручивать сами стэпы (Он не подходит, так как нужен именно inline синтаксис):
fluentStruct := NewFluentStruct()
result := fluentStruct.Step1().Step2().GetResult()
2) Переработать метод Step1, чтобы он не модифицировал предыдущий объект, а возвращал новый, то есть получается иммутабельная версия - вариант приемлимый, но я боюсь не будет ли он более затратный по памяти:
func (f FluentStruct) Step1() FluentStruct {
return FluentStruct{append(f.queue, smth)}
}
Заранее спасибо за помощь!
func NewFluentStruct() *FluentStruct {
return &FluentStruct{}
}


Aleksey
12.01.2018
15:15:34

Kirill
12.01.2018
15:15:35

Aleksandr
12.01.2018
15:16:21

Kirill
12.01.2018
15:16:35
А, ну т.е. я все правильно делаю

Aleksandr
12.01.2018
15:16:37
и мне не нравится идея пинговать на каждый запрос
я не утверждал этого
пинговать на каждый getDB - не очень как по мне, а учитывая что там паника дальше, то это то же самое что и у тебя

Kirill
12.01.2018
15:18:13
Тогда я тебя не понимаю)
Пинговать на каждый запрос - плохо, так?
Тогда как проверять, что БД не легла?

Vladislav
12.01.2018
15:19:07
SELECT 42 (FROM DUAL)
с каких пор пинг гарантирует работоспособность базы? о_0

Aleksandr
12.01.2018
15:19:47

Vladislav
12.01.2018
15:20:04
база упала, сервер нет