//commonActionDBS. Returns action for cli app bind with handler for current db item func commonActionDBS(cflags *cliFlags, name string, a action.Actioner, sqlRequired bool, before, after, errtrg actionTriggerDBS) func(ctx *cli.Context) { return func(ctx *cli.Context) { logger.Trace.Println("command", name) defer logger.Trace.Println("command", name, "done") d := db.GetInstance() defer checkErr(d.Close) cflags.SetContext(ctx) dbsSource, err := getDatabases(cflags, d) if err != nil { panic(err) } if len(dbsSource) == 0 { panic(fmt.Errorf("databases not found")) } paramGetter := createParametersGetter(ctx) var sc *sqlcommand.SQLCommand if sqlRequired { sc = parseSQLFromArgs(ctx) if sc == nil { panic(fmt.Errorf("SQL not found")) } logger.Debug.Printf("select sql:%q, %v\n", sc.Script, sc.Params) } contextRun := action.NewContext() if err := parseOthersFlagsForRunContext(ctx, contextRun); err != nil { panic(err) } doTrigger(before, dbsSource, contextRun) if _, e := run.Run(dbsSource, sc, a, contextRun, paramGetter); e != nil { logger.Error.Println(e) doTrigger(errtrg, dbsSource, contextRun) } else { if success, ok := contextRun.Get("success").(int); !ok || success == 0 { doTrigger(errtrg, dbsSource, contextRun) } else { doTrigger(after, dbsSource, contextRun) } } } }
func runItem(d db.Database, s *sqlcommand.SQLCommand, doaction action.Actioner, ctx *action.Context, pget parametergetter.ParameterGetter) error { logger.Trace.Println("runItem") defer logger.Trace.Println(d.Code, "runItem done") if s != nil { logger.Trace.Println(d.Code, s.Script) } wg.Add(1) ctx.IncInt("exec", 1) params := ctx.Get("Params").([]parameters.Parameter) go func() { timeout := ctx.GetDef("timeout", 0).(int) defer wg.Done() var ( ctxExec context.Context cancel context.CancelFunc ) ch := make(chan bool) if timeout > 0 { ctxExec, cancel = context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) } else { ctxExec, cancel = context.WithCancel(context.Background()) } defer cancel() localCtx := action.NewContext() go func() { defer func() { ch <- true close(ch) }() ctx.Set("context"+d.Code, localCtx) ctx.Set("iscancel", ch) localCtx.Snap.Start() localCtx.Set("success", false) connectionString, e := paramsreplace.Replace(d.ConnectionString, params) if e != nil { ctx.IncInt("failed", 1) logger.Error.Println(e) return } logger.Debug.Println(d.Code, "Connection string:", connectionString) connection, err := rdb.Open(d.Engine, connectionString) if err != nil { ctx.IncInt("failed", 1) logger.Error.Println(d.Code, err) return } defer func() { if err := connection.Close(); err != nil { panic(err) } else { logger.Trace.Printf("%s disconnected", d.Code) } }() err = doaction(d, connection, s, ctx) if err != nil { if err.Error() != "cancel" { ctx.IncInt("failed", 1) localCtx.Snap.Done(err) logger.Error.Println(d.Code, err) if !ctx.GetDef("silent", false).(bool) { fmt.Fprintf(os.Stdout, "%s: %s\n", d.Code, strings.Replace(err.Error(), "\n", " ", -1)) } } return } localCtx.Set("success", true) ctx.IncInt("success", 1) localCtx.Snap.Done(nil) runtime.Gosched() }() select { case <-ch: logger.Trace.Println("operation done w/o timeout") return case <-ctxExec.Done(): err := ctxExec.Err() logger.Trace.Printf("operation done: %s\n", err) ctx.IncInt("failed", 1) localCtx.Snap.Done(err) logger.Error.Println(d.Code, err) // ch <- true return } }() return nil }