Skip to content

Commit 96b5111

Browse files
authored
fix: add unique index for plugin installation to prevent duplicate entries (#528)
1 parent 8e5743a commit 96b5111

2 files changed

Lines changed: 2 additions & 48 deletions

File tree

internal/service/install_plugin.go

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package service
33
import (
44
"errors"
55
"fmt"
6-
"time"
76

87
"github.com/gin-gonic/gin"
98
controlpanel "github.com/langgenius/dify-plugin-daemon/internal/core/control_panel"
@@ -105,49 +104,21 @@ func InstallMultiplePluginsToTenant(
105104
})
106105
}
107106

108-
// acquire locks to prevent concurrent installation of the same plugin
109-
lockKeys := make(map[string]string, len(pluginUniqueIdentifiers))
110-
releaseLocks := func() {
111-
for _, key := range lockKeys {
112-
if err := cache.Unlock(key); err != nil {
113-
log.Error("failed to unlock key %s: %v", key, err)
114-
}
115-
}
116-
}
117-
for _, pluginUniqueIdentifier := range pluginUniqueIdentifiers {
118-
lockKey := fmt.Sprintf("plugin:install:%s:%s", tenantId, pluginUniqueIdentifier.PluginID())
119-
if err := cache.Lock(lockKey, time.Minute*10, time.Millisecond*100); err != nil {
120-
releaseLocks()
121-
if err == cache.ErrLockTimeout {
122-
return exception.BadRequestError(errors.New("plugin installation is already in progress")).ToResponse()
123-
}
124-
return exception.InternalServerError(err).ToResponse()
125-
}
126-
lockKeys[pluginUniqueIdentifier.PluginID()] = lockKey
127-
}
128-
129107
// create tasks for each plugin
130108
statuses := buildTaskStatuses(pluginUniqueIdentifiers, declarations)
131109
taskRegistry, err := createInstallTasks(tenants, statuses)
132110
if err != nil {
133-
releaseLocks()
134111
return exception.InternalServerError(err).ToResponse()
135112
}
136113
taskIDs := taskRegistry.IDs()
137114

138115
for _, job := range jobs {
139116
jobCopy := job
140-
lockKey := lockKeys[jobCopy.Identifier.PluginID()]
141117
// start a new goroutine to install the plugin
142118
routine.Submit(routinepkg.Labels{
143119
routinepkg.RoutineLabelKeyModule: "service",
144120
routinepkg.RoutineLabelKeyMethod: "InstallPlugin",
145121
}, func() {
146-
defer func() {
147-
if err := cache.Unlock(lockKey); err != nil {
148-
log.Error("failed to unlock key %s: %v", lockKey, err)
149-
}
150-
}()
151122
tasks.ProcessInstallJob(
152123
manager,
153124
tenants,
@@ -288,15 +259,6 @@ func UpgradePlugin(
288259
return exception.InternalServerError(err).ToResponse()
289260
}
290261

291-
// acquire lock to prevent concurrent upgrade of the same plugin
292-
lockKey := fmt.Sprintf("plugin:install:%s:%s", tenantId, newPluginUniqueIdentifier.PluginID())
293-
if err := cache.Lock(lockKey, time.Minute*10, time.Millisecond*100); err != nil {
294-
if err == cache.ErrLockTimeout {
295-
return exception.BadRequestError(errors.New("plugin installation is already in progress")).ToResponse()
296-
}
297-
return exception.InternalServerError(err).ToResponse()
298-
}
299-
300262
// construct tenant jobs
301263
tenants := []string{tenantId}
302264

@@ -315,9 +277,6 @@ func UpgradePlugin(
315277

316278
taskRegistry, err := createInstallTasks(tenants, statuses)
317279
if err != nil {
318-
if unlockErr := cache.Unlock(lockKey); unlockErr != nil {
319-
log.Error("failed to unlock key %s: %v", lockKey, unlockErr)
320-
}
321280
return exception.InternalServerError(err).ToResponse()
322281
}
323282

@@ -327,11 +286,6 @@ func UpgradePlugin(
327286
routinepkg.RoutineLabelKeyModule: "service",
328287
routinepkg.RoutineLabelKeyMethod: "UpgradePlugin",
329288
}, func() {
330-
defer func() {
331-
if err := cache.Unlock(lockKey); err != nil {
332-
log.Error("failed to unlock key %s: %v", lockKey, err)
333-
}
334-
}()
335289
tasks.ProcessUpgradeJob(
336290
manager,
337291
tenants,

internal/types/models/installation.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ type PluginInstallationStatus string
44

55
type PluginInstallation struct {
66
Model
7-
TenantID string `json:"tenant_id" gorm:"index;type:uuid;"`
8-
PluginID string `json:"plugin_id" gorm:"index;size:255"`
7+
TenantID string `json:"tenant_id" gorm:"index;uniqueIndex:idx_tenant_plugin;type:uuid;"`
8+
PluginID string `json:"plugin_id" gorm:"index;uniqueIndex:idx_tenant_plugin;size:255"`
99
PluginUniqueIdentifier string `json:"plugin_unique_identifier" gorm:"index;size:255"`
1010
RuntimeType string `json:"runtime_type" gorm:"size:127"`
1111
EndpointsSetups int `json:"endpoints_setups"`

0 commit comments

Comments
 (0)