예제 #1
0
파일: remotedb.go 프로젝트: arteev/dsql
//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)
			}
		}

	}
}
예제 #2
0
파일: run.go 프로젝트: arteev/dsql
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
}