Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PMM-12896 Add limit for actions/jobs executed on the same DB at the same time #2898

Merged
merged 35 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
972bb1c
Add limit for actions/jobs executed on the same DB at the same time
artemgavrilov Mar 13, 2024
5a5a6a7
PMM-12896 Fix
artemgavrilov Mar 13, 2024
4463f1a
PMM-12896 Fixes
artemgavrilov Mar 13, 2024
af550fb
PMM-12896 Fix
artemgavrilov Mar 13, 2024
06743cf
PMM-12896 Fix tests
artemgavrilov Mar 14, 2024
dba0886
PMM-12896 Improvements, fixes, comments, tests
artemgavrilov Mar 14, 2024
4211fad
PMM-12896 Make per DB capacity configurable
artemgavrilov Mar 14, 2024
d5eefa2
PMM-12896 Fix
artemgavrilov Mar 14, 2024
a77e999
PMM-12896 Improve tests
artemgavrilov Mar 14, 2024
e003f5c
PMM-12896 Linter fixes
artemgavrilov Mar 14, 2024
be6e0bf
PMM-12896 Refactoring
artemgavrilov Mar 15, 2024
fb3a35f
PMM-12896 Fix comment
artemgavrilov Mar 15, 2024
2971596
Merge remote-tracking branch 'origin/main' into PMM-12896-limit-conns…
artemgavrilov Mar 19, 2024
e59a244
PMM-12896 Fix DSN method for PT mysql summary action
artemgavrilov Mar 19, 2024
306b2f5
PMM-12896 Fix bug in local semaphores releasing
artemgavrilov Mar 19, 2024
74f18c4
PMM-12896 Refactoring
artemgavrilov Mar 19, 2024
55b7e05
PMM-12896 Refactoring
artemgavrilov Mar 19, 2024
5d35524
PMM-12896 Refactoring
artemgavrilov Mar 19, 2024
206ca7c
PMM-12896 Refactoring
artemgavrilov Mar 19, 2024
5229182
PMM-12896 Fix test
artemgavrilov Mar 19, 2024
477790b
PMM-12896 Fix tests
artemgavrilov Mar 19, 2024
fab890b
Merge remote-tracking branch 'origin/main' into PMM-12896-limit-conns…
artemgavrilov Mar 19, 2024
428e5f1
Revert "PMM-12896 Fix tests"
artemgavrilov Mar 19, 2024
9c3b9f7
PMM-12896 Fix tests
artemgavrilov Mar 19, 2024
9484c03
PMM-12896 Use timeout only for job/action exectuion, not for resource…
artemgavrilov Mar 20, 2024
1156da4
PMM-12896 Refactoring
artemgavrilov Mar 20, 2024
5ab80bd
Update agent/config/config.go
artemgavrilov Mar 21, 2024
a779937
Update agent/runner/actions/mongodb_explain_action.go
artemgavrilov Mar 21, 2024
e9fec6f
Update agent/runner/actions/postgresql_query_select_action.go
artemgavrilov Mar 21, 2024
fb5530f
Merge remote-tracking branch 'origin/main' into PMM-12896-limit-conns…
artemgavrilov Mar 21, 2024
d1c0a9e
PMM-12896 Refactoring
artemgavrilov Mar 21, 2024
be9f781
PMM-12896 Mute linter
artemgavrilov Mar 21, 2024
270c974
Merge branch 'main' into PMM-12896-limit-conns-num-from-jobs-runner
artemgavrilov Mar 25, 2024
154761d
Merge branch 'main' into PMM-12896-limit-conns-num-from-jobs-runner
yurkovychv May 20, 2024
256c8b1
Merge branch 'main' into PMM-12896-limit-conns-num-from-jobs-runner
artemgavrilov May 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion agent/agents/mongodb/internal/profiler/profiler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,9 @@ func testProfiler(t *testing.T, url string) {
Query: findBucket.Common.Example,
}

ex := actions.NewMongoDBExplainAction(id, 5*time.Second, params, os.TempDir())
ex, err := actions.NewMongoDBExplainAction(id, 5*time.Second, params, os.TempDir())
require.NoError(t, err)

ctx, cancel := context.WithTimeout(context.Background(), ex.Timeout())
defer cancel()
res, err := ex.Run(ctx)
Expand Down
31 changes: 18 additions & 13 deletions agent/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,9 +454,10 @@ func (c *Client) handleStartActionRequest(p *agentpb.StartActionRequest) error {

cfg := c.cfg.Get()
var action actions.Action
var err error
switch params := p.Params.(type) {
case *agentpb.StartActionRequest_MysqlExplainParams:
action = actions.NewMySQLExplainAction(p.ActionId, timeout, params.MysqlExplainParams)
action, err = actions.NewMySQLExplainAction(p.ActionId, timeout, params.MysqlExplainParams)

case *agentpb.StartActionRequest_MysqlShowCreateTableParams:
action = actions.NewMySQLShowCreateTableAction(p.ActionId, timeout, params.MysqlShowCreateTableParams)
Expand All @@ -468,13 +469,13 @@ func (c *Client) handleStartActionRequest(p *agentpb.StartActionRequest) error {
action = actions.NewMySQLShowIndexAction(p.ActionId, timeout, params.MysqlShowIndexParams)

case *agentpb.StartActionRequest_PostgresqlShowCreateTableParams:
action = actions.NewPostgreSQLShowCreateTableAction(p.ActionId, timeout, params.PostgresqlShowCreateTableParams, cfg.Paths.TempDir)
action, err = actions.NewPostgreSQLShowCreateTableAction(p.ActionId, timeout, params.PostgresqlShowCreateTableParams, cfg.Paths.TempDir)

case *agentpb.StartActionRequest_PostgresqlShowIndexParams:
action = actions.NewPostgreSQLShowIndexAction(p.ActionId, timeout, params.PostgresqlShowIndexParams, cfg.Paths.TempDir)
action, err = actions.NewPostgreSQLShowIndexAction(p.ActionId, timeout, params.PostgresqlShowIndexParams, cfg.Paths.TempDir)

case *agentpb.StartActionRequest_MongodbExplainParams:
action = actions.NewMongoDBExplainAction(p.ActionId, timeout, params.MongodbExplainParams, cfg.Paths.TempDir)
action, err = actions.NewMongoDBExplainAction(p.ActionId, timeout, params.MongodbExplainParams, cfg.Paths.TempDir)

case *agentpb.StartActionRequest_MysqlQueryShowParams:
action = actions.NewMySQLQueryShowAction(p.ActionId, timeout, params.MysqlQueryShowParams)
Expand All @@ -483,13 +484,13 @@ func (c *Client) handleStartActionRequest(p *agentpb.StartActionRequest) error {
action = actions.NewMySQLQuerySelectAction(p.ActionId, timeout, params.MysqlQuerySelectParams)

case *agentpb.StartActionRequest_PostgresqlQueryShowParams:
action = actions.NewPostgreSQLQueryShowAction(p.ActionId, timeout, params.PostgresqlQueryShowParams, cfg.Paths.TempDir)
action, err = actions.NewPostgreSQLQueryShowAction(p.ActionId, timeout, params.PostgresqlQueryShowParams, cfg.Paths.TempDir)

case *agentpb.StartActionRequest_PostgresqlQuerySelectParams:
action = actions.NewPostgreSQLQuerySelectAction(p.ActionId, timeout, params.PostgresqlQuerySelectParams, cfg.Paths.TempDir)
action, err = actions.NewPostgreSQLQuerySelectAction(p.ActionId, timeout, params.PostgresqlQuerySelectParams, cfg.Paths.TempDir)

case *agentpb.StartActionRequest_MongodbQueryGetparameterParams:
action = actions.NewMongoDBQueryAdmincommandAction(
action, err = actions.NewMongoDBQueryAdmincommandAction(
p.ActionId,
timeout,
params.MongodbQueryGetparameterParams.Dsn,
Expand All @@ -499,7 +500,7 @@ func (c *Client) handleStartActionRequest(p *agentpb.StartActionRequest) error {
cfg.Paths.TempDir)

case *agentpb.StartActionRequest_MongodbQueryBuildinfoParams:
action = actions.NewMongoDBQueryAdmincommandAction(
action, err = actions.NewMongoDBQueryAdmincommandAction(
p.ActionId,
timeout,
params.MongodbQueryBuildinfoParams.Dsn,
Expand All @@ -509,7 +510,7 @@ func (c *Client) handleStartActionRequest(p *agentpb.StartActionRequest) error {
cfg.Paths.TempDir)

case *agentpb.StartActionRequest_MongodbQueryGetcmdlineoptsParams:
action = actions.NewMongoDBQueryAdmincommandAction(
action, err = actions.NewMongoDBQueryAdmincommandAction(
p.ActionId,
timeout,
params.MongodbQueryGetcmdlineoptsParams.Dsn,
Expand All @@ -519,7 +520,7 @@ func (c *Client) handleStartActionRequest(p *agentpb.StartActionRequest) error {
cfg.Paths.TempDir)

case *agentpb.StartActionRequest_MongodbQueryReplsetgetstatusParams:
action = actions.NewMongoDBQueryAdmincommandAction(
action, err = actions.NewMongoDBQueryAdmincommandAction(
p.ActionId,
timeout,
params.MongodbQueryReplsetgetstatusParams.Dsn,
Expand All @@ -529,7 +530,7 @@ func (c *Client) handleStartActionRequest(p *agentpb.StartActionRequest) error {
cfg.Paths.TempDir)

case *agentpb.StartActionRequest_MongodbQueryGetdiagnosticdataParams:
action = actions.NewMongoDBQueryAdmincommandAction(
action, err = actions.NewMongoDBQueryAdmincommandAction(
p.ActionId,
timeout,
params.MongodbQueryGetdiagnosticdataParams.Dsn,
Expand Down Expand Up @@ -565,6 +566,10 @@ func (c *Client) handleStartActionRequest(p *agentpb.StartActionRequest) error {
return errors.Wrapf(agenterrors.ErrInvalidArgument, "invalid action type request: %T", params)
}

if err != nil {
return errors.Wrap(err, "failed to create action")
}

return c.runner.StartAction(action)
}

Expand Down Expand Up @@ -645,7 +650,7 @@ func (c *Client) handleStartJobRequest(p *agentpb.StartJobRequest) error {
return errors.WithStack(err)
}

job, err = jobs.NewMongoDBBackupJob(p.JobId, timeout, j.MongodbBackup.Name, &dsn, locationConfig,
job, err = jobs.NewMongoDBBackupJob(p.JobId, timeout, j.MongodbBackup.Name, dsn, locationConfig,
j.MongodbBackup.EnablePitr, j.MongodbBackup.DataModel, j.MongodbBackup.Folder)
if err != nil {
return err
Expand Down Expand Up @@ -678,7 +683,7 @@ func (c *Client) handleStartJobRequest(p *agentpb.StartJobRequest) error {
}

job = jobs.NewMongoDBRestoreJob(p.JobId, timeout, j.MongodbRestoreBackup.Name,
j.MongodbRestoreBackup.PitrTimestamp.AsTime(), &dsn, locationConfig,
j.MongodbRestoreBackup.PitrTimestamp.AsTime(), dsn, locationConfig,
c.supervisor, j.MongodbRestoreBackup.Folder, j.MongodbRestoreBackup.PbmMetadata.Name)
default:
return errors.Errorf("unknown job type: %T", j)
Expand Down
2 changes: 2 additions & 0 deletions agent/runner/actions/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ type Action interface {
Type() string
// Timeout returns Job timeout.
Timeout() time.Duration
// DSN returns Data Source Name required for the Action.
DSN() string
// Run runs an Action and returns output and error.
Run(ctx context.Context) ([]byte, error)

Expand Down
27 changes: 18 additions & 9 deletions agent/runner/actions/mongodb_explain_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,32 @@ import (
"github.com/percona/pmm/api/agentpb"
)

const mongoDBExplainActionType = "mongodb-explain"

type mongodbExplainAction struct {
id string
timeout time.Duration
params *agentpb.StartActionRequest_MongoDBExplainParams
tempDir string
dsn string
}

var errCannotExplain = fmt.Errorf("cannot explain this type of query")

// NewMongoDBExplainAction creates a MongoDB EXPLAIN query Action.
func NewMongoDBExplainAction(id string, timeout time.Duration, params *agentpb.StartActionRequest_MongoDBExplainParams, tempDir string) Action {
func NewMongoDBExplainAction(id string, timeout time.Duration, params *agentpb.StartActionRequest_MongoDBExplainParams, tempDir string) (Action, error) {
dsn, err := templates.RenderDSN(params.Dsn, params.TextFiles, filepath.Join(tempDir, strings.ToLower(mongoDBExplainActionType), id))
artemgavrilov marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, errors.WithStack(err)
}
artemgavrilov marked this conversation as resolved.
Show resolved Hide resolved

return &mongodbExplainAction{
id: id,
timeout: timeout,
params: params,
tempDir: tempDir,
}
dsn: dsn,
}, nil
}

// ID returns an Action ID.
Expand All @@ -62,17 +71,17 @@ func (a *mongodbExplainAction) Timeout() time.Duration {

// Type returns an Action type.
func (a *mongodbExplainAction) Type() string {
return "mongodb-explain"
return mongoDBExplainActionType
}

// DSN returns a DSN for the Action.
artemgavrilov marked this conversation as resolved.
Show resolved Hide resolved
func (a *mongodbExplainAction) DSN() string {
return a.dsn
}

// Run runs an action and returns output and error.
func (a *mongodbExplainAction) Run(ctx context.Context) ([]byte, error) {
dsn, err := templates.RenderDSN(a.params.Dsn, a.params.TextFiles, filepath.Join(a.tempDir, strings.ToLower(a.Type()), a.id))
if err != nil {
return nil, errors.WithStack(err)
}

opts, err := mongo_fix.ClientOptionsForDSN(dsn)
opts, err := mongo_fix.ClientOptionsForDSN(a.dsn)
if err != nil {
return nil, errors.WithStack(err)
}
Expand Down
8 changes: 6 additions & 2 deletions agent/runner/actions/mongodb_explain_action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ func TestMongoDBExplain(t *testing.T) {
Query: `{"ns":"test.coll","op":"query","query":{"k":{"$lte":{"$numberInt":"1"}}}}`,
}

ex := NewMongoDBExplainAction(id, 0, params, os.TempDir())
ex, err := NewMongoDBExplainAction(id, 0, params, os.TempDir())
require.NoError(t, err)

res, err := ex.Run(ctx)
assert.Nil(t, err)

Expand Down Expand Up @@ -130,7 +132,9 @@ func TestNewMongoDBExplain(t *testing.T) {
Query: string(query),
}

ex := NewMongoDBExplainAction(id, 0, params, os.TempDir())
ex, err := NewMongoDBExplainAction(id, 0, params, os.TempDir())
require.NoError(t, err)

res, err := ex.Run(ctx)
assert.NoError(t, err)

Expand Down
25 changes: 16 additions & 9 deletions agent/runner/actions/mongodb_query_admincommand_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
"github.com/percona/pmm/api/agentpb"
)

const mongoDBQueryAdminCommandActionType = "mongodb-query-admincommand"

type mongodbQueryAdmincommandAction struct {
id string
timeout time.Duration
Expand All @@ -40,7 +42,12 @@ type mongodbQueryAdmincommandAction struct {
}

// NewMongoDBQueryAdmincommandAction creates a MongoDB adminCommand query action.
func NewMongoDBQueryAdmincommandAction(id string, timeout time.Duration, dsn string, files *agentpb.TextFiles, command string, arg interface{}, tempDir string) Action {
func NewMongoDBQueryAdmincommandAction(id string, timeout time.Duration, dsn string, files *agentpb.TextFiles, command string, arg interface{}, tempDir string) (Action, error) {
artemgavrilov marked this conversation as resolved.
Show resolved Hide resolved
dsn, err := templates.RenderDSN(dsn, files, filepath.Join(tempDir, strings.ToLower(mongoDBQueryAdminCommandActionType), id))
if err != nil {
return nil, errors.WithStack(err)
}

return &mongodbQueryAdmincommandAction{
id: id,
timeout: timeout,
Expand All @@ -49,7 +56,7 @@ func NewMongoDBQueryAdmincommandAction(id string, timeout time.Duration, dsn str
command: command,
arg: arg,
tempDir: tempDir,
}
}, nil
}

// ID returns an action ID.
Expand All @@ -64,17 +71,17 @@ func (a *mongodbQueryAdmincommandAction) Timeout() time.Duration {

// Type returns an action type.
func (a *mongodbQueryAdmincommandAction) Type() string {
return "mongodb-query-admincommand"
return mongoDBQueryAdminCommandActionType
}

// DSN returns a DSN for the Action.
func (a *mongodbQueryAdmincommandAction) DSN() string {
return a.dsn
}

// Run runs an action and returns output and error.
func (a *mongodbQueryAdmincommandAction) Run(ctx context.Context) ([]byte, error) {
dsn, err := templates.RenderDSN(a.dsn, a.files, filepath.Join(a.tempDir, strings.ToLower(a.Type()), a.id))
if err != nil {
return nil, errors.WithStack(err)
}

opts, err := mongo_fix.ClientOptionsForDSN(dsn)
opts, err := mongo_fix.ClientOptionsForDSN(a.dsn)
if err != nil {
return nil, errors.WithStack(err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,9 @@ func TestMongoDBActionsReplWithSSL(t *testing.T) {

func runAction(t *testing.T, id string, timeout time.Duration, dsn string, files *agentpb.TextFiles, command string, arg interface{}, tempDir string) []byte { //nolint:unparam
t.Helper()
a := NewMongoDBQueryAdmincommandAction(id, timeout, dsn, files, command, arg, tempDir)
a, err := NewMongoDBQueryAdmincommandAction(id, timeout, dsn, files, command, arg, tempDir)
require.NoError(t, err)

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
b, err := a.Run(ctx)
Expand Down Expand Up @@ -227,7 +229,9 @@ func replSetGetStatusAssertionsReplicated(t *testing.T, b []byte) { //nolint:the
}

func replSetGetStatusAssertionsStandalone(t *testing.T, id string, timeout time.Duration, dsn string, files *agentpb.TextFiles, command string, arg interface{}, tempDir string) { //nolint:thelper
a := NewMongoDBQueryAdmincommandAction(id, timeout, dsn, files, command, arg, tempDir)
a, err := NewMongoDBQueryAdmincommandAction(id, timeout, dsn, files, command, arg, tempDir)
require.NoError(t, err)

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
b, err := a.Run(ctx)
Expand Down
39 changes: 22 additions & 17 deletions agent/runner/actions/mysql_explain_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,27 @@ var errCannotEncodeExplainResponse = errors.New("cannot JSON encode the explain

// NewMySQLExplainAction creates MySQL Explain Action.
// This is an Action that can run `EXPLAIN` command on MySQL service with given DSN.
func NewMySQLExplainAction(id string, timeout time.Duration, params *agentpb.StartActionRequest_MySQLExplainParams) Action {
func NewMySQLExplainAction(id string, timeout time.Duration, params *agentpb.StartActionRequest_MySQLExplainParams) (Action, error) {
if params.Query == "" {
return nil, errors.New("Query to EXPLAIN is empty")
}

// You cant run Explain on trimmed queries.
if strings.HasSuffix(params.Query, "...") {
return nil, errors.New("EXPLAIN failed because the query was too long and trimmed. Set max-query-length to a larger value.") //nolint:revive
artemgavrilov marked this conversation as resolved.
Show resolved Hide resolved
artemgavrilov marked this conversation as resolved.
Show resolved Hide resolved
}

// Explain is supported only for DML queries.
// https://dev.mysql.com/doc/refman/8.0/en/using-explain.html
if !isDMLQuery(params.Query) {
return nil, errors.New("Functionality EXPLAIN is supported only for DML queries (SELECT, INSERT, UPDATE, DELETE, REPLACE)")
artemgavrilov marked this conversation as resolved.
Show resolved Hide resolved
}

return &mysqlExplainAction{
id: id,
timeout: timeout,
params: params,
}
}, nil
}

// ID returns an Action ID.
Expand All @@ -77,23 +92,13 @@ func (a *mysqlExplainAction) Type() string {
return "mysql-explain"
}

// DSN returns a DSN for the Action.
func (a *mysqlExplainAction) DSN() string {
return a.params.Dsn
}

// Run runs an Action and returns output and error.
func (a *mysqlExplainAction) Run(ctx context.Context) ([]byte, error) {
if a.params.Query == "" {
return nil, errors.New("Query to EXPLAIN is empty")
}

// You cant run Explain on trimmed queries.
if strings.HasSuffix(a.params.Query, "...") {
return nil, errors.New("EXPLAIN failed because the query was too long and trimmed. Set max-query-length to a larger value.") //nolint:revive
}

// Explain is supported only for DML queries.
// https://dev.mysql.com/doc/refman/8.0/en/using-explain.html
if !isDMLQuery(a.params.Query) {
return nil, errors.New("Functionality EXPLAIN is supported only for DML queries (SELECT, INSERT, UPDATE, DELETE, REPLACE)")
}

a.params.Query = queryparser.GetMySQLFingerprintFromExplainFingerprint(a.params.Query)

// query has a copy of the original params.Query field if the query is a SELECT or the equivalent
Expand Down
Loading
Loading