Documentation
¶
Index ¶
- Constants
- Variables
- func ConnectInternal() error
- func GetStatusInternal(db SureSQLDB, setNodeStatus bool) (orm.NodeStatusStruct, error)
- func InitDB(force bool) error
- func LoadConfigFromDB(db *SureSQLDB) error
- func LoadSettingsFromDB(db *SureSQLDB) error
- func OverwriteConfigFromEnvironment()
- func PingPong() string
- type ConfigTable
- type EnvConfig
- type InsertRequest
- type QueryRequest
- type QueryResponse
- type QueryResponseSQL
- type SQLRequest
- type SQLResponse
- type SettingTable
- type Settings
- type SettingsMap
- type StandardResponse
- type SureSQLDB
- type SureSQLDBMSConfig
- type SureSQLNode
- func (n *SureSQLNode) ApplyAllConfig() bool
- func (n *SureSQLNode) ApplySettings(category, key string) bool
- func (n SureSQLNode) GetDBConnectionByToken(token string) (SureSQLDB, error)
- func (n *SureSQLNode) GetStatusFromSettings(conf SureSQLDBMSConfig)
- func (n SureSQLNode) IsPoolAvailable() bool
- func (n SureSQLNode) PrintWelcomePretty()
- func (n *SureSQLNode) RenameDBConnection(old, new string)
- type TokenTable
Constants ¶
const ( // DEFAULT LEADER NODE LEADER_NODE_NUMBER = 1 // for readibility INTERNAL_MODE = false // not copying the result into current node's status NODE_MODE = true // copying the result into current node's status // ConfigTable Categories and keys SETTING_CATEGORY_TOKEN = "token" SETTING_KEY_TOKEN_EXP = "token_exp" // value int: in minutes SETTING_KEY_REFRESH_EXP = "refresh_exp" // value int: in minutes SETTING_KEY_TOKEN_TTL = "token_ttl" // value int: in minutes, beat for checking expiration SETTING_CATEGORY_CONNECTION = "connection" SETTING_KEY_MAX_POOL = "max_pool" // value int: 0 overwrite pool_on, meaning no pooling, automatically pool_on=false SETTING_KEY_ENABLE_POOL = "pool_on" // value string: true or false SETTING_CATEGORY_NODES = "nodes" SETTING_KEY_NODE_NAME = "node_name" // value string: node_number;hostname;ip;mode SETTING_NODE_DELIMITER = "|" SETTING_CATEGORY_SYSTEM = "system" SETTING_KEY_LABEL = "label" // value string: label for this node SETTING_KEY_IP = "ip" // value string: database name SETTING_KEY_HOST = "host" // value string: hostname SETTING_KEY_PORT = "port" // value string: port number SETTING_KEY_SSL = "ssl" // value bool(int): true or false SETTING_KEY_DBMS = "dbms" // value string: rqlite or other later implementation SETTING_KEY_MODE = "mode" // value string: 'r', 'w', 'rw' SETTING_KEY_NODES = "nodes" // value int: total nodes in the cluster SETTING_KEY_NODE_NUMBER = "node_number" // value int: node number for this server SETTING_KEY_IS_INIT_DONE = "is_init_done" // value bool(int): DB init is done SETTING_KEY_IS_SPLIT_WRITE = "is_split_write" // value bool(int): split write SETTING_KEY_ENCRYPTION_METHOD = "encryption_method" // value string: "aes", "rsa", "none" SETTING_CATEGORY_EMPTY = "nocategory" )
const ( SURESQL_ENV_FILE = ".env.suresql" APP_NAME = "SureSQL" APP_VERSION = "0.0.1" )
const ( MIGRATION_DIRECTORY = "migrations/" MIGRATION_UP_FILES_SIGNATURE = "_up.sql" )
const ( // Default Token settings DEFAULT_TOKEN_EXPIRES_MINUTES = 24 * 60 * time.Minute // every 24 hours DEFAULT_REFRESH_EXPIRES_MINUTES = 48 * 60 * time.Minute // every 48 hours DEFAULT_TTL_TICKER_MINUTES = 5 * time.Minute // every [value] minute, check for expiration for ttl // Default HTTP timeouts // DEFAULT_CONNECTION_TIMEOUT = 60 * time.Second DEFAULT_TIMEOUT = 60 * time.Second DEFAULT_RETRY_TIMEOUT = 60 * time.Second DEFAULT_RETRY = 3 // Default Pool settings DEFAULT_MAX_POOL = 25 DEFAULT_POOL_ENABLED = true )
Variables ¶
var ( CurrentNode SureSQLNode ReloadEnvironment bool = false // Standard error, cannot use constant on struct // Should be constant instead? ErrNoDBConnection medaerror.MedaError = medaerror.MedaError{Message: "no db connection"} ErrDBInitializedAlready medaerror.MedaError = medaerror.MedaError{Message: "DB already initialized"} // ErrTokenNotFound medaerror.MedaError = medaerror.MedaError{Message: "token not found"} // ErrInvalidRequest medaerror.MedaError = medaerror.MedaError{Message: "invalid request param or body"} // ErrWrongPassword medaerror.MedaError = medaerror.MedaError{Message: "password missmatch"} SchemaTable string = "" )
GLOBAL VAR
var (
ServerStartTime time.Time
)
Functions ¶
func ConnectInternal ¶
func ConnectInternal() error
This should be run the first time this package got imported, which is connecting to the DB locally / internally. Not yet used by the client.
func GetStatusInternal ¶
func GetStatusInternal(db SureSQLDB, setNodeStatus bool) (orm.NodeStatusStruct, error)
func InitDB ¶
This is more like migrating data from MIGRATION_DIRECTORY TODO: fix the printout to use metrics package so we can have the time elapsed information. Make sure to call this AFTER connect internal is called!! Because we need the DB connection already.
func LoadConfigFromDB ¶
LoadConfigFromDB loads settings from _settings table
func LoadSettingsFromDB ¶ added in v0.0.2
func OverwriteConfigFromEnvironment ¶ added in v0.0.2
func OverwriteConfigFromEnvironment()
if DB settings is not there, get from environment. DB's settings table always wins
Types ¶
type ConfigTable ¶
type ConfigTable struct {
ID int `json:"id,omitempty" db:"id"`
Label string `json:"label,omitempty" db:"label"`
IP string `json:"ip,omitempty" db:"ip"`
Host string `json:"host,omitempty" db:"host"`
Port string `json:"port,omitempty" db:"port"`
SSL bool `json:"ssl,omitempty" db:"ssl"`
DBMS string `json:"dbms,omitempty" db:"dbms"`
Mode string `json:"mode,omitempty" db:"mode"`
Nodes int `json:"nodes,omitempty" db:"nodes"` // total number of nodes in the cluster
NodeNumber int `json:"node_number,omitempty" db:"node_number"` // this is node number .. X
NodeID int `json:"node_id,omitempty" db:"node_id"` // this is node ID from rqlite cluster
IsInitDone bool `json:"is_init_done,omitempty" db:"is_init_done"`
IsSplitWrite bool `json:"is_split_write,omitempty" db:"is_split_write"`
EncryptionMethod string `json:"encryption_method,omitempty" db:"encryption_method"`
TokenExp time.Duration `json:"token_exp,omitempty" db:"token_exp"` // token expiration in minutes
RefreshExp time.Duration `json:"refresh_exp,omitempty" db:"refresh_exp"` // refresh token expiration in minutes
TTLTicker time.Duration `json:"ttl_ticker,omitempty" db:"ttl_ticker"` // ttl ticker to check expiration in minutes
EnvConfig
}
This is the config for the current SureSQL node, it inserted inside the table!
func (ConfigTable) TableName ¶
func (s ConfigTable) TableName() string
type EnvConfig ¶ added in v0.0.2
type EnvConfig struct {
Token string `json:"token,omitempty" db:"token"`
RefreshToken string `json:"refresh_token,omitempty" db:"refresh_token"`
JWEKey string `json:"jwe_key,omitempty" db:"jwe_key"`
JWTKey string `json:"jwt_key,omitempty" db:"jwt_key"`
APIKey string `json:"api_key,omitempty" db:"api_key"`
ClientID string `json:"client_id,omitempty" db:"client_id"`
HttpTimeout time.Duration `json:"http_timeout,omitempty" db:"http_timeout"`
RetryTimeout time.Duration `json:"retry_timeout,omitempty" db:"retry_timeout"`
MaxRetries int `json:"max_retries,omitempty" db:"max_retries"`
}
This is reserved to be configuration that usually taken from environment variables for safety
type InsertRequest ¶
type InsertRequest struct {
Records []orm.DBRecord `json:"records"` // Records to insert
Queue bool `json:"queue,omitempty"` // Whether to use queue operations (optional)
SameTable bool `json:"same_table,omitempty"` // Indicates if all records belong to the same table
}
===== Used in handle_Insert endpoints InsertRequest represents the request structure for inserting records
type QueryRequest ¶
type QueryRequest struct {
Table string `json:"table"` // Table name for queries
Condition *orm.Condition `json:"condition,omitempty"` // Optional condition for filtering
SingleRow bool `json:"single_row,omitempty"` // If true, return only first row
}
===== Used in handle_Query endpoints QueryRequest represents the simplified request structure for executing SELECT queries
type QueryResponse ¶
type QueryResponse struct {
Records []orm.DBRecord `json:"records"` // Always returns as array, even for single record
ExecutionTime float64 `json:"execution_time"`
Count int `json:"count"`
}
QueryResponse represents the response structure for query results
type QueryResponseSQL ¶
type QueryResponseSQL []QueryResponse
QueryResponse represents the response structure for query results
type SQLRequest ¶
type SQLRequest struct {
Statements []string `json:"statements,omitempty"` // Raw SQL statements to execute
ParamSQL []orm.ParametereizedSQL `json:"param_sql,omitempty"` // Parameterized SQL statements to execute
SingleRow bool `json:"single_row,omitempty"` // If true, return only first row
}
===== Used in handle_SQL endpoints SQLRequest represents the request structure for executing SQL commands: UPDATE, DELETE, DROP, INSERT, SELECT
type SQLResponse ¶
type SQLResponse struct {
Results []orm.BasicSQLResult `json:"results"` // Results for each executed statement
ExecutionTime float64 `json:"execution_time"` // Total execution time in milliseconds
RowsAffected int `json:"rows_affected"` // Total number of rows affected
}
SQLResponse represents the response structure for SQL execution results
type SettingTable ¶ added in v0.0.2
type SettingTable struct {
ID int `json:"id,omitempty" db:"id"`
Category string `json:"category,omitempty" db:"category"`
DataType string `json:"data_type,omitempty" db:"data_type"`
SettingKey string `json:"setting_key,omitempty" db:"setting_key"`
TextValue string `json:"text_value,omitempty" db:"text_value"`
FloatValue float64 `json:"float_value,omitempty" db:"float_value"`
IntValue int `json:"int_value,omitempty" db:"int_value"`
}
This is how we store the config for SureSQL. It can contains the peers information, timeouts etc (depends on the category) Ie: category: token , rows are: ConfigKey: token_exp , IntValue: 20 (in minutes) ConfigKey: refresh_exp , IntValue: 200 (in minutes) ConfigKey: token_ttl , IntValue: 5 (in minutes)
func (SettingTable) GetValue ¶ added in v0.0.2
func (c SettingTable) GetValue() interface{}
GetValue returns the value of the config entry as an interface{} based on data_type
func (SettingTable) TableName ¶ added in v0.0.2
func (c SettingTable) TableName() string
type Settings ¶ added in v0.0.2
type Settings map[string]SettingsMap
Map SettingsMap by the category, which is the same as inside SettingTable.Category Finding key based on category: Settings[category][Key] ie: Settings[token][token_exp].IntValue =
func (Settings) SettingExist ¶ added in v0.0.2
func (c Settings) SettingExist(category, key string) (SettingTable, bool)
By category and key
type SettingsMap ¶ added in v0.0.2
type SettingsMap map[string]SettingTable
map SettingTable by the key (string) which is same as SettingTable.SettingKey instead of using array, this is faster to search for specific setting key
func (SettingsMap) SettingExist ¶ added in v0.0.2
func (c SettingsMap) SettingExist(key string) (SettingTable, bool)
type StandardResponse ¶
type StandardResponse struct {
Status int `json:"status"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
StandardResponse is a structured response format for all API responses
type SureSQLDB ¶
func NewDatabase ¶
func NewDatabase(conf SureSQLDBMSConfig) (SureSQLDB, error)
Making connection to internal DB This is where implementation selection happens, right now is only RQlite
type SureSQLDBMSConfig ¶ added in v0.0.2
type SureSQLDBMSConfig struct {
Host string `json:"host,omitempty" db:"host"`
Port string `json:"port,omitempty" db:"port"`
Username string `json:"username,omitempty" db:"username"` // this is not used, we use _users table instead
Password string `json:"password,omitempty" db:"password"` // this is not used, we use _users table instead
Database string `json:"database,omitempty" db:"database"`
SSL bool `json:"ssl,omitempty" db:"ssl"`
Options string `json:"options,omitempty" db:"options"`
Consistency string `json:"consistency,omitempty" db:"consistency"`
// below are not yet used. Previously those are SureSQL Config instead of DBMS config
URL string `json:"url,omitempty" db:"url"`
EnvConfig
}
This is config needed by SureSQL to connect to Internal DB (DBMS), at this point only RQLite
func LoadDBMSConfigFromEnvironment ¶ added in v0.0.2
func LoadDBMSConfigFromEnvironment() SureSQLDBMSConfig
Reading internal DB configuration for this SureSQL Node, from environment TODO: maybe add second return parameter: error, so caller can check if error then quit the app
func (*SureSQLDBMSConfig) GenerateGoRQLiteURL ¶ added in v0.0.2
func (sc *SureSQLDBMSConfig) GenerateGoRQLiteURL()
NOTE: this is not used, because we are using direct-rqlite implementation If using the gorqlite implementation, then we need to put username+password in the URL then gorqlite use this to connect to the rqlite server
func (*SureSQLDBMSConfig) GenerateRQLiteURL ¶ added in v0.0.2
func (sc *SureSQLDBMSConfig) GenerateRQLiteURL()
If using direct-rqlite (our own) implementation, then no need, because when direct-rqlite connects to RQLite server it will use basic-auth format for the username and password.
func (*SureSQLDBMSConfig) PrintDebug ¶ added in v0.0.2
func (sc *SureSQLDBMSConfig) PrintDebug(secure bool)
type SureSQLNode ¶
type SureSQLNode struct {
InternalConfig SureSQLDBMSConfig `json:"internal_config,omitempty" db:"internal_config"`
InternalAPI string `json:"internal_api,omitempty" db:"internal_api"` // This is for the node internal API (CRUD users)
Config ConfigTable `json:"settings,omitempty" db:"settings"` // Settings for this node, from DB table
Settings Settings `json:"configs,omitempty" db:"configs"` // Configs for this node, from DB table
Status orm.NodeStatusStruct `json:"status,omitempty" db:"status"` // Status for SureSQL DB Node that is standard from orm
InternalConnection SureSQLDB `json:"internal_connection,omitempty" db:"internal_connection"` // master connection to InternalDB
DBConnections *medattlmap.TTLMap `json:"db_connections,omitempty" db:"db_connections"` // another connection based on Token
MaxPool int `json:"max_pool,omitempty" db:"max_pool"` // total nodes for this project
IsPoolEnabled bool `json:"is_poolenabled,omitempty" db:"is_poolenabled"` // if this DB already initialized
IsEncrypted bool `json:"is_encrypted,omitempty" db:"is_encrypted"` // none/AES/Bcrypt (already in Settings)
}
This is the whole SureSQL Node is all about NOTE: do we need IP? because we can put IP address in the hostname field if we are connecting based on IP.
func (*SureSQLNode) ApplyAllConfig ¶
func (n *SureSQLNode) ApplyAllConfig() bool
This is to get all the config table and put it as SureSQLNode config
func (*SureSQLNode) ApplySettings ¶ added in v0.0.2
func (n *SureSQLNode) ApplySettings(category, key string) bool
Apply config if they are changed from DB, only few that can be changed and effected at run-time NOTE: this is hard-coded
func (SureSQLNode) GetDBConnectionByToken ¶
func (n SureSQLNode) GetDBConnectionByToken(token string) (SureSQLDB, error)
Get the DB connection from pool based on token
func (*SureSQLNode) GetStatusFromSettings ¶
func (n *SureSQLNode) GetStatusFromSettings(conf SureSQLDBMSConfig)
This is the status for SureSQL Nodes (not the internal DBMS nodes) Status is pretty much taken from Settings, but this is used for response
func (SureSQLNode) IsPoolAvailable ¶
func (n SureSQLNode) IsPoolAvailable() bool
Check if pool is enabled, and max pool has not reached
func (SureSQLNode) PrintWelcomePretty ¶
func (n SureSQLNode) PrintWelcomePretty()
Print the node information for console log
func (*SureSQLNode) RenameDBConnection ¶
func (n *SureSQLNode) RenameDBConnection(old, new string)
rename the key for DB connection pool to use new token, this is usually because refresh token. TODO: please don't use this anymore, when token is refreshed, the DB connection should be deleted - and re-create it again fresh with new expiration same with the token expiration.
type TokenTable ¶
type TokenTable struct {
ID string `json:"id,omitempty" db:"id"`
UserID string `json:"user_id,omitempty" db:"user_id"`
Token string `json:"token,omitempty" db:"token"`
Refresh string `json:"refresh_token,omitempty" db:"refresh_token"`
TokenExpiresAt time.Time `json:"token_expired_at,omitempty" db:"token_expired_at"`
RefreshExpiresAt time.Time `json:"refresh_expired_at,omitempty" db:"refresh_expired_at"`
CreatedAt time.Time `json:"created_at,omitempty" db:"created_at"`
// additional members
UserName string
}
Originally this was saved in DB as table, but maybe Redis or some auto-expire system is better
func (TokenTable) TableName ¶
func (t TokenTable) TableName() string