Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Adding context to existing code

Adding context to existing code

Alexey Palazhchenko

March 24, 2019
Tweet

More Decks by Alexey Palazhchenko

Other Decks in Programming

Transcript

  1. Solution 1: «just» add ctx QueryRow(string, ...interface{}) *Row QueryRow(context.Context, string,

    ...interface{}) *Row Query(string, ...interface{}) (*Rows, error) Query(context.Context, string, ...interface{}) (*Rows, error) Exec(string, ...interface{}) (Result, error) Exec(context.Context, string, ...interface{}) (Result, error)
  2. Solution 1 problems • Internal code – large-scale refactoring. •

    Use context.TODO(). • «TODO is recognized by static analysis tools that determine whether Contexts are propagated correctly in a program.»
  3. Solution 1 problems • Internal code – large-scale refactoring. •

    Use context.TODO(). • «TODO is recognized by static analysis tools that determine whether Contexts are propagated correctly in a program.» • This tool does not exist.
  4. Solution 2x QueryRow(string, ...interface{}) *Row QueryRowContext(context.Context, string, ...interface{}) *Row Query(string,

    ...interface{}) (*Rows, error) QueryContext(context.Context, string, ...interface{}) (*Rows, error) Exec(string, ...interface{}) (Result, error) ExecContext(context.Context, string, ...interface{}) (Result, error)
  5. Solution 2x Delete(record Record) error DeleteFrom(view View, tail string, args

    ...interface{}) (uint, error) Exec(query string, args ...interface{}) (sql.Result, error) FindAllFrom(view View, column string, args ...interface{}) ([]Struct, error) FindByPrimaryKeyFrom(table Table, pk interface{}) (Record, error) FindByPrimaryKeyTo(record Record, pk interface{}) error FindOneFrom(view View, column string, arg interface{}) (Struct, error) FindOneTo(str Struct, column string, arg interface{}) error FindRows(view View, column string, arg interface{}) (*sql.Rows, error) Insert(str Struct) error InsertColumns(str Struct, columns ...string) error InsertMulti(structs ...Struct) error NextRow(str Struct, rows *sql.Rows) error QualifiedColumns(view View) []string QualifiedView(view View) string Query(query string, args ...interface{}) (*sql.Rows, error) QueryRow(query string, args ...interface{}) *sql.Row Reload(record Record) error Save(record Record) error SelectAllFrom(view View, tail string, args ...interface{}) (structs []Struct, err error) SelectOneFrom(view View, tail string, args ...interface{}) (Struct, error) SelectOneTo(str Struct, tail string, args ...interface{}) error SelectRows(view View, tail string, args ...interface{}) (*sql.Rows, error) Update(record Record) error UpdateColumns(record Record, columns ...string) error UpdateView(str Struct, columns []string, tail string, args ...interface{}) (uint, error)
  6. Solution 3 type Querier struct { Context context.Context } func

    (q *Querier) QueryRow(query string, args ...interface{}) *sql.Row
  7. https://golang.org/pkg/context/ «Do not store Contexts inside a struct type; instead,

    pass a Context explicitly to each function that needs it. The Context should be the first parameter, typically named ctx.» Solution 3 «problem»
  8. https://github.com/golang/go/issues/14660 «While we've told people not to add contexts to

    structs, I think that guidance is over-aggressive. The real advice is not to store contexts. They should be passed along like parameters. But if the struct is essentially just a parameter, it's okay.» Solution 3
  9. Solution 3b type Querier struct { ctx context.Context } func

    (q *Querier) WithContext(ctx context.Context) *Querier func (q *Querier) QueryRow(query string, args ...interface{}) *sql.Row
  10. Conclusion • "Just" add ctx to internal code. • Consider

    your options for the external code. • Know best practices beyond their short versions.