mattermost/server/public/plugin/driver.go
Agniva De Sarker effb99301e
MM-56402: Introduce a pluginID to track RPC DB connections (#26424)
Previously, we relied on the plugin to close the DB connections
on shutdown. While this keeps the code simple, there is no guarantee
that the plugin author will remember to close the DB.

In that case, it's better to track the connections from the server side
and close them in case they weren't closed already. This complicates
the API slightly, but it's a price we need to pay.

https://mattermost.atlassian.net/browse/MM-56402

```release-note
We close any remaining unclosed DB RPC connections
after a plugin shuts down.
```


Co-authored-by: Jesse Hallam <jesse.hallam@gmail.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
2024-04-16 18:53:26 +05:30

75 lines
2.7 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package plugin
import (
"database/sql/driver"
)
// ResultContainer contains the output from the LastInsertID
// and RowsAffected methods for a given set of rows.
// It is used to embed another round-trip to the server,
// and helping to avoid tracking results on the server.
type ResultContainer struct {
LastID int64
LastIDError error
RowsAffected int64
RowsAffectedError error
}
// Driver is a sql driver interface that is used by plugins to perform
// raw SQL queries without opening DB connections by themselves. This interface
// is not subject to backward compatibility guarantees and is only meant to be
// used by plugins built by the Mattermost team.
type Driver interface {
// Connection
Conn(isMaster bool) (string, error)
ConnPing(connID string) error
ConnClose(connID string) error
ConnQuery(connID, q string, args []driver.NamedValue) (string, error) // rows
ConnExec(connID, q string, args []driver.NamedValue) (ResultContainer, error) // result
// Transaction
Tx(connID string, opts driver.TxOptions) (string, error)
TxCommit(txID string) error
TxRollback(txID string) error
// Statement
Stmt(connID, q string) (string, error)
StmtClose(stID string) error
StmtNumInput(stID string) int
StmtQuery(stID string, args []driver.NamedValue) (string, error) // rows
StmtExec(stID string, args []driver.NamedValue) (ResultContainer, error) // result
// Rows
RowsColumns(rowsID string) []string
RowsClose(rowsID string) error
RowsNext(rowsID string, dest []driver.Value) error
RowsHasNextResultSet(rowsID string) bool
RowsNextResultSet(rowsID string) error
RowsColumnTypeDatabaseTypeName(rowsID string, index int) string
RowsColumnTypePrecisionScale(rowsID string, index int) (int64, int64, bool)
// TODO: add this
// RowsColumnScanType(rowsID string, index int) reflect.Type
// Note: the following cannot be implemented because either MySQL or PG
// does not support it. So this implementation has to be a common subset
// of both DB implementations.
// RowsColumnTypeLength(rowsID string, index int) (int64, bool)
// RowsColumnTypeNullable(rowsID string, index int) (bool, bool)
// ResetSession(ctx context.Context) error
// IsValid() bool
}
// AppDriver is an extension of the Driver interface to capture non-RPC APIs.
type AppDriver interface {
Driver
// ConnWithPluginID is only used by the server, and isn't exposed via the RPC API.
ConnWithPluginID(isMaster bool, pluginID string) (string, error)
// This is an extra method needed to shutdown connections
// after a plugin shuts down.
ShutdownConns(pluginID string)
}