Skip to content

Commit f355158

Browse files
authored
Merge pull request #386 from devlights/devlights/add-sql-database-example-377
Add database example -- ping.go
2 parents 7dc861c + 75da1c9 commit f355158

File tree

3 files changed

+105
-0
lines changed

3 files changed

+105
-0
lines changed

internal/examples/basic/databases/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
|file|example name|note|
66
|----|------------|----|
77
|open.go|db\_open|sql.Open 関数の使い方についてサンプルです|
8+
|ping.go|db\_ping|(*sql.DB).Ping の使い方についてのサンプルです|

internal/examples/basic/databases/examples.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ func NewRegister() mappings.Register {
1616
// Regist -- 登録します.
1717
func (r *register) Regist(m mappings.ExampleMapping) {
1818
m["db_open"] = Open
19+
m["db_ping"] = Ping
1920
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package databases
2+
3+
import (
4+
"context"
5+
"database/sql"
6+
"time"
7+
8+
"github.com/devlights/gomy/output"
9+
"github.com/devlights/gomy/times"
10+
_ "github.com/mattn/go-sqlite3"
11+
)
12+
13+
// Ping は、 (*sql.DB).Ping の使い方についてのサンプルです.
14+
func Ping() error {
15+
var (
16+
rootCtx = context.Background()
17+
mainCtx, mainCxl = context.WithCancel(rootCtx)
18+
)
19+
defer mainCxl()
20+
21+
var (
22+
db *sql.DB
23+
err error
24+
)
25+
26+
if db, err = sql.Open(Driver, Dsn); err != nil {
27+
return err
28+
}
29+
defer db.Close()
30+
31+
//
32+
// Ping -- 生存確認を行う
33+
//
34+
// 通信のPINGと同様に、対象の *sql.DB が生きているかどうかを確認する
35+
// まだ一度もクエリを発行していない状態で、このメソッドを呼ぶと接続が行われる
36+
//
37+
// 通信プログラムの場合と同様で、長時間接続を持続するアプリケーションを作成している場合などに
38+
// 接続か切れていないか確認する場合などで利用できる
39+
//
40+
// PingとPingContextの2つのメソッドがあり、前者はコンテキスト無しでブロッキングされ
41+
// 後者はコンテキストを渡すバージョン。
42+
//
43+
44+
// Ping メソッド(ブロッキング)
45+
if err = db.Ping(); err != nil {
46+
return err
47+
}
48+
49+
// PingContext メソッド(コンテキストを渡せる)
50+
var (
51+
pingCtx, pingCxl = context.WithTimeout(mainCtx, 100*time.Millisecond)
52+
)
53+
defer pingCxl()
54+
55+
if err = db.PingContext(pingCtx); err != nil {
56+
return err
57+
}
58+
59+
//
60+
// 定周期で生存確認
61+
//
62+
var (
63+
hbCtx, hbCxl = context.WithTimeout(mainCtx, 6*time.Second)
64+
interval = 1 * time.Second
65+
)
66+
defer hbCxl()
67+
68+
ctx := heartbeat(hbCtx, db, interval)
69+
70+
<-hbCtx.Done()
71+
<-ctx.Done()
72+
73+
return nil
74+
}
75+
76+
func heartbeat(ctx context.Context, db *sql.DB, interval time.Duration) context.Context {
77+
ctx, stop := context.WithCancel(ctx)
78+
79+
go func() {
80+
defer stop()
81+
82+
LOOP:
83+
for {
84+
select {
85+
case <-ctx.Done():
86+
break LOOP
87+
case t := <-time.After(1 * time.Second):
88+
pt := times.HHmmss(t)
89+
90+
if err := db.Ping(); err != nil {
91+
output.Stderrf("[heartbeat]", "[Error]:%s (%s)\n", err, pt)
92+
continue
93+
}
94+
95+
output.Stdoutf("[heartbeat]", "[Ok]: %s\n", pt)
96+
}
97+
}
98+
99+
output.Stdoutl("[heartbeat]", "done")
100+
}()
101+
102+
return ctx
103+
}

0 commit comments

Comments
 (0)