Skip to content

Instantly share code, notes, and snippets.

@daneharrigan
Created June 1, 2020 18:18
Show Gist options
  • Save daneharrigan/0e9a5dfb3b435a4ae71554bcd1f41d8b to your computer and use it in GitHub Desktop.
Save daneharrigan/0e9a5dfb3b435a4ae71554bcd1f41d8b to your computer and use it in GitHub Desktop.
// General ideas:
// - A project hides SQL in custom db package and exposes CRUD methods
// - I can generate that db package interface with protoc
// - time.Time has to be converted into timestamp.Timestamp for a gRPC service to use the value
// - database/sql writes to a time.Time and I convert that into timestamp.Timestamp.
// All conversions are kept in a single package.
// - gRPC has error types that map to SQL errors such as not found, already exists, etc.
// - database/sql will only write a timestamp to `time.Time`
// - I map errors like sql.ErrNoRows to gRPC's equivalent
// ----
// package pb
// A regular gRPC server interface
type DBServer interface {
CreateAccount(context.Context, *CreateAccountRequest) (*CreateAccountResponse, error)
}
// ----
// package db
// A DB/gRPC interface
type DB interface {
pb.DBServer
WithTx() (pb.DBServer, Tx, error)
}
type Tx interface {
Commit() error
Rollback() error
}
// New takes an SQL connection returns a DB which is the implemented pb.DBServer with an additional method WithTx().
// WithTx() returns a pb.DBServer because you cannot create nested transactions.
func New(*sql.DB) DB {
// ...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment