44 "context"
55 "fmt"
66 "io/ioutil"
7- "os "
7+ "math/rand "
88 "time"
99
1010 "github.com/cybertec-postgresql/pg_timetable/internal/config"
@@ -51,6 +51,18 @@ type PgEngine struct {
5151 config.CmdOptions
5252 // NOTIFY messages passed verification are pushed to this channel
5353 chainSignalChan chan ChainSignal
54+ pid int32
55+ }
56+
57+ // Getpid returns the pseudo-random process ID to use for the session identification.
58+ // Previously `os.Getpid()` used but this approach is not producing unique IDs for docker containers
59+ // where all IDs are the same across all running containers, e.g. 1
60+ func (pge * PgEngine ) Getpid () int32 {
61+ if pge .pid == 0 {
62+ rand .Seed (time .Now ().UnixNano ())
63+ pge .pid = rand .Int31 ()
64+ }
65+ return pge .pid
5466}
5567
5668var sqls = []string {sqlDDL , sqlJSONSchema , sqlCronFunctions , sqlJobFunctions }
@@ -61,12 +73,12 @@ func New(ctx context.Context, cmdOpts config.CmdOptions, logger log.LoggerHooker
6173 var wt int = WaitTime
6274 var err error
6375 pge := & PgEngine {
64- logger ,
65- nil ,
66- cmdOpts ,
67- make (chan ChainSignal , 64 ),
76+ l : logger ,
77+ ConfigDb : nil ,
78+ CmdOptions : cmdOpts ,
79+ chainSignalChan : make (chan ChainSignal , 64 ),
6880 }
69- pge .l .WithField ("PID" , os .Getpid ()).Debug ("Starting new session... " )
81+ pge .l .WithField ("PID" , pge .Getpid ()).Info ("Starting new session... " )
7082 connctx , conncancel := context .WithTimeout (ctx , time .Duration (cmdOpts .Connection .Timeout )* time .Second )
7183 defer conncancel ()
7284
@@ -106,7 +118,12 @@ func New(ctx context.Context, cmdOpts config.CmdOptions, logger log.LoggerHooker
106118// NewDB creates pgengine instance for already opened database connection, allowing to bypass a parameters based credentials.
107119// We assume here all checks for proper schema validation are done beforehannd
108120func NewDB (DB PgxPoolIface , args ... string ) * PgEngine {
109- return & PgEngine {log .Init (config.LoggingOpts {LogLevel : "error" }), DB , * config .NewCmdOptions (args ... ), make (chan ChainSignal , 64 )}
121+ return & PgEngine {
122+ l : log .Init (config.LoggingOpts {LogLevel : "error" }),
123+ ConfigDb : DB ,
124+ CmdOptions : * config .NewCmdOptions (args ... ),
125+ chainSignalChan : make (chan ChainSignal , 64 ),
126+ }
110127}
111128
112129// getPgxConnConfig transforms standard connestion string to pgx specific one with
@@ -159,7 +176,7 @@ func (pge *PgEngine) getPgxConnConfig() *pgxpool.Config {
159176
160177// AddLogHook adds a new pgx log hook to logrus logger
161178func (pge * PgEngine ) AddLogHook (ctx context.Context ) {
162- pge .l .AddHook (NewHook (ctx , pge . ConfigDb , pge . ClientName , 500 , pge .Logging .LogDBLevel ))
179+ pge .l .AddHook (NewHook (ctx , pge , pge .Logging .LogDBLevel ))
163180}
164181
165182// QueryRowIface specifies interface to use QueryRow method
@@ -182,7 +199,7 @@ func (pge *PgEngine) TryLockClientName(ctx context.Context, conn QueryRowIface)
182199 }
183200 var wt int = WaitTime
184201 for {
185- sql := fmt .Sprintf ("SELECT timetable.try_lock_client_name(%d, $worker$%s$worker$)" , os .Getpid (), pge .ClientName )
202+ sql := fmt .Sprintf ("SELECT timetable.try_lock_client_name(%d, $worker$%s$worker$)" , pge .Getpid (), pge .ClientName )
186203 var locked bool
187204 err = conn .QueryRow (ctx , sql ).Scan (& locked )
188205 if err != nil {
@@ -262,7 +279,7 @@ DELETE FROM timetable.active_session WHERE client_name = $1`
262279 pge .ConfigDb = nil
263280}
264281
265- //Reconnect keeps trying reconnecting every `waitTime` seconds till connection established
282+ // Reconnect keeps trying reconnecting every `waitTime` seconds till connection established
266283func (pge * PgEngine ) Reconnect (ctx context.Context ) bool {
267284 for pge .ConfigDb .Ping (ctx ) != nil {
268285 pge .l .Info ("Connection to the server was lost. Waiting for " , WaitTime , " sec..." )
0 commit comments