You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As the primary developer for @sphireinc, I created a common Database interface and related base-level implementations for:
Redis
ScyllaDB (can be abused for Cassandra)
SurrealDB
Clickhouse
MySQL
SQLite
Aerospike
Kafka
Postgres
For the most part, they're just thin wrappers that create a connection given the common interface. For the implementations, I would remove the HealthCheck stuff and anything else that comes from the "ServerStatusCommon.types" package, and probably any of the Query functions as they're largely internal and not general.
This is the interface:
package database
import"github.com/sphireinc/ServerStatusCommon/types"// Service represents a service that interacts with a database.typeServiceinterface {
// Health returns a map of health status information.// The keys and values in the map are service-specific.Health() (types.HealthCheck, bool)
// Close terminates the database connection.// It returns an error if the connection cannot be closed.Close() error// // Query executes a predefined query and returns the results as a slice of maps.// // Each map represents a row with column names as keys and corresponding values.// Query(fileName string) (CommonRows, error)
}
and, the Scylla implementation:
package database
import (
"fmt""github.com/gocql/gocql""github.com/labstack/echo/v4""github.com/scylladb/gocqlx/v2""github.com/scylladb/gocqlx/v2/qb""github.com/scylladb/gocqlx/v2/table""github.com/sphireinc/ServerStatusCommon/types""log""os"
)
typeHealthstruct {
Keystring`db:"key"`Bootstrappedstring`db:"bootstrapped"`BroadcastAddressstring`db:"broadcast_address"`CqlVersionstring`db:"cql_version"`DataCenterstring`db:"data_center"`HostIDstring`db:"host_id"`ListenAddressstring`db:"listen_address"`Rackstring`db:"rack"`ReleaseVersionstring`db:"release_version"`RPCAddressstring`db:"rpc_address"`SchemaVersionstring`db:"schema_version"`
}
varHealthMetadata= table.Metadata{
Name: "system.local",
Columns: []string{"key", "bootstrapped", "broadcast_address", "cql_version",
"data_center", "host_id", "listen_address", "rack", "release_version", "rpc_address", "schema_version"},
PartKey: []string{"key"},
}
varHealthTable=table.New(HealthMetadata)
// ScyllaService represents the ScyllaDB database service.typeScyllaServicestruct {
session gocqlx.Sessionlogger echo.Logger
}
varscyllaInstance*ScyllaService// NewScyllaService creates a new Scylla service instance.funcNewScyllaService(logger echo.Logger) Service {
logger.Info("creating new ScyllaService")
// Reuse ConnectionifscyllaInstance!=nil {
returnscyllaInstance
}
cluster:=gocql.NewCluster(os.Getenv("SCYLLA_HOSTS"))
cluster.Keyspace=os.Getenv("SCYLLA_KEYSPACE")
cluster.Consistency=gocql.Quorumcluster.Authenticator= gocql.PasswordAuthenticator{
Username: os.Getenv("SCYLLA_USERNAME"),
Password: os.Getenv("SCYLLA_PASSWORD"),
}
session, err:=gocqlx.WrapSession(cluster.CreateSession())
iferr!=nil {
log.Fatal(err)
}
scyllaInstance=&ScyllaService{
session: session,
logger: logger,
}
logger.Info("created new ScyllaService")
returnscyllaInstance
}
// Close closes the database connection.func (s*ScyllaService) Close() error {
log.Printf("Disconnected from database")
s.session.Close()
returnnil
}
// Query executes a predefined query and returns the results as *gocqlx.Iter.// It returns an error if the query fails or if there are no rows.func (s*ScyllaService) Query(actionstring, tbl*table.Table, paramsany, where qb.Cmp) (*gocqlx.Iterx, error) {
varstmtstringvarnames []stringvarq*gocqlx.Queryxswitchaction {
case"INSERT":
stmt, names=qb.Insert(tbl.Name()).Columns(tbl.Metadata().Columns...).ToCql()
case"UPDATE":
stmt, names=qb.Update(tbl.Name()).Set(tbl.Metadata().Columns...).Where(where).ToCql()
case"SELECT":
stmt, names=qb.Select(tbl.Name()).Columns(tbl.Metadata().Columns...).ToCql()
default:
returnnil, fmt.Errorf("unsupported action: %s", action)
}
q=s.session.Query(stmt, names).BindStruct(params)
iter:=q.Iter()
ifiter.NumRows() ==0 {
_=iter.Close()
returnnil, fmt.Errorf("no rows found")
}
returniter, nil
}
// Health checks the health of the database connection by pinging the database.func (s*ScyllaService) Health() (types.HealthCheck, bool) {
s.logger.Info("checking database health for ScyllaDB")
response:=types.NewHealthCheck("scylla", "datastore")
// // [CODE OMITTED] // //returnresponse, true
}
Would something like this be beneficial for the framework? If so, I would be more than happy to "donate" the watered down code, no strings attached.
The text was updated successfully, but these errors were encountered:
@anthdm sounds good! I was thinking of still keeping db.New() and just adding more consts (like DriverSqlite3) while integrating the additional dbs. I'll keep an eye on this issue awaiting your decision on how to move forward.
As the primary developer for @sphireinc, I created a common Database interface and related base-level implementations for:
For the most part, they're just thin wrappers that create a connection given the common interface. For the implementations, I would remove the HealthCheck stuff and anything else that comes from the "ServerStatusCommon.types" package, and probably any of the
Query
functions as they're largely internal and not general.This is the interface:
and, the Scylla implementation:
Would something like this be beneficial for the framework? If so, I would be more than happy to "donate" the watered down code, no strings attached.
The text was updated successfully, but these errors were encountered: