Skip to content

Commit 780bffa

Browse files
committed
fix: refactor 1
1 parent 4ed65f6 commit 780bffa

File tree

9 files changed

+65
-278
lines changed

9 files changed

+65
-278
lines changed

internal/backend/database/database.go

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ type DBInterface interface {
2424
UpdateServerDetails(id int64, name, url string) error
2525

2626
// Tool Management
27-
UpsertTool(tool models.Tool) (added bool, err error)
27+
UpsertTool(tool models.Tool) error
2828
ListTools() ([]models.Tool, error)
2929
ListToolsByServerID(serverID int64) ([]models.Tool, error)
3030
RemoveToolsByServerID(serverID int64) error
@@ -80,7 +80,7 @@ func (db *DB) ensureSchema() error {
8080
name TEXT NOT NULL,
8181
description TEXT,
8282
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
83-
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, -- Added this column
83+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
8484
FOREIGN KEY (source_server_id) REFERENCES mcp_servers(id) ON DELETE CASCADE,
8585
UNIQUE (source_server_id, external_id)
8686
);
@@ -156,7 +156,7 @@ func (db *DB) RemoveServer(id int64) error {
156156
return fmt.Errorf("failed to get rows affected for remove server ID %d: %w", id, err)
157157
}
158158
if rowsAffected == 0 {
159-
return fmt.Errorf("server with ID %d not found for removal", id)
159+
return nil
160160
}
161161
return nil
162162
}
@@ -173,7 +173,6 @@ func (db *DB) UpdateServerStatus(id int64, state models.ConnectionState, lastErr
173173

174174
// UpdateServerDetails updates the name and URL for a server.
175175
func (db *DB) UpdateServerDetails(id int64, name, url string) error {
176-
// Add validation if needed (e.g., check for URL uniqueness if changing)
177176
query := `UPDATE mcp_servers SET name = ?, url = ? WHERE id = ?`
178177
_, err := db.Exec(query, name, url, id)
179178
if err != nil {
@@ -185,46 +184,36 @@ func (db *DB) UpdateServerDetails(id int64, name, url string) error {
185184
// --- Tool CRUD ---
186185

187186
// UpsertTool inserts a new tool or updates an existing one based on external_id and source_server_id.
188-
// It returns true if a new row was inserted, false if an existing row was updated.
189-
func (db *DB) UpsertTool(tool models.Tool) (added bool, err error) {
187+
func (db *DB) UpsertTool(tool models.Tool) (err error) {
190188
tx, err := db.Beginx()
191189
if err != nil {
192-
return false, fmt.Errorf("failed to begin transaction for upsert tool: %w", err)
190+
return fmt.Errorf("failed to begin transaction for upsert tool: %w", err)
193191
}
194-
// Ensure rollback on error
192+
// Ensure rollback on error, commit on success
195193
defer func() {
196-
if p := recover(); p != nil {
197-
_ = tx.Rollback()
198-
panic(p) // Re-panic after rollback
199-
} else if err != nil {
200-
_ = tx.Rollback() // Rollback on normal error
201-
} else {
202-
err = tx.Commit() // Commit on success
203-
if err != nil {
204-
err = fmt.Errorf("failed to commit transaction for upsert tool: %w", err)
194+
if err != nil {
195+
// Rollback only if the error is not nil on exit
196+
if rbErr := tx.Rollback(); rbErr != nil {
197+
// Log or wrap the rollback error if necessary, but prioritize the original error
198+
fmt.Printf("ERROR: Failed to rollback transaction after error: %v (original error: %v)\n", rbErr, err)
205199
}
200+
return // Keep the original error
201+
}
202+
// Commit if err is nil
203+
err = tx.Commit()
204+
if err != nil {
205+
err = fmt.Errorf("failed to commit transaction for upsert tool: %w", err)
206206
}
207207
}()
208208

209-
// 1. Check if the tool already exists
210-
var exists int
211-
checkQuery := `SELECT COUNT(*) FROM tools WHERE external_id = ? AND source_server_id = ?`
212-
err = tx.Get(&exists, checkQuery, tool.ExternalID, tool.SourceServerID)
213-
if err != nil && err != sql.ErrNoRows { // Allow ErrNoRows here, though count should return 0
214-
err = fmt.Errorf("failed to check tool existence: %w", err)
215-
return // Defer will rollback
216-
}
217-
218-
added = (exists == 0)
219-
220-
// 2. Perform the UPSERT
209+
// Perform the UPSERT
221210
upsertQuery := `
222211
INSERT INTO tools (external_id, source_server_id, name, description, created_at, updated_at)
223-
VALUES (:external_id, :source_server_id, :name, :description, :created_at, :updated_at)
224-
ON CONFLICT(external_id, source_server_id) DO UPDATE SET
225-
name = excluded.name,
226-
description = excluded.description,
227-
updated_at = excluded.updated_at
212+
VALUES (:external_id, :source_server_id, :name, :description, :created_at, :updated_at)
213+
ON CONFLICT(external_id, source_server_id) DO UPDATE SET
214+
name = excluded.name,
215+
description = excluded.description,
216+
updated_at = excluded.updated_at
228217
`
229218
now := time.Now().UTC()
230219
tool.CreatedAt = now // Set creation time (only used on INSERT)
@@ -245,8 +234,8 @@ func (db *DB) UpsertTool(tool models.Tool) (added bool, err error) {
245234
return // Defer will rollback
246235
}
247236

248-
// Defer will commit if err is nil
249-
return added, err
237+
// Defer handles commit/rollback
238+
return err
250239
}
251240

252241
// ListTools retrieves all tools from the database.

internal/backend/database/database_test.go

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -288,14 +288,10 @@ func TestUpsertTool(t *testing.T) {
288288
}
289289

290290
// 1. Insert
291-
// Capture both return values
292-
added, err := db.UpsertTool(tool1)
291+
err = db.UpsertTool(tool1)
293292
if err != nil {
294293
t.Fatalf("UpsertTool (insert) failed: %v", err)
295294
}
296-
if !added {
297-
t.Error("UpsertTool (insert) should have returned added=true")
298-
}
299295

300296
// Verify insert by listing
301297
tools, err := db.ListToolsByServerID(serverID)
@@ -334,14 +330,10 @@ func TestUpsertTool(t *testing.T) {
334330
Description: "Does awesome things better", // Changed description
335331
}
336332

337-
// Capture both return values
338-
added, err = db.UpsertTool(updatedTool1)
333+
err = db.UpsertTool(updatedTool1)
339334
if err != nil {
340335
t.Fatalf("UpsertTool (update) failed: %v", err)
341336
}
342-
if added {
343-
t.Error("UpsertTool (update) should have returned added=false")
344-
}
345337

346338
// Verify update
347339
tools, err = db.ListToolsByServerID(serverID)
@@ -380,17 +372,15 @@ func TestUpsertTool_UniqueConstraint(t *testing.T) {
380372
}
381373

382374
// Add tool for server 1
383-
// Capture both return values (using _)
384-
_, err := db.UpsertTool(tool)
375+
err := db.UpsertTool(tool)
385376
if err != nil {
386377
t.Fatalf("UpsertTool for server 1 failed: %v", err)
387378
}
388379

389380
// Add tool with same ExternalID but for server 2 (should succeed)
390381
tool.SourceServerID = serverID2
391382
tool.Description = "From Server 2"
392-
// Capture both return values (using _)
393-
_, err = db.UpsertTool(tool)
383+
err = db.UpsertTool(tool)
394384
if err != nil {
395385
t.Fatalf("UpsertTool for server 2 with same external ID failed: %v", err)
396386
}
@@ -423,15 +413,13 @@ func TestListTools(t *testing.T) {
423413
}
424414

425415
for _, tool := range toolsS1 {
426-
// Capture both return values (using _)
427-
_, err := db.UpsertTool(tool)
416+
err := db.UpsertTool(tool)
428417
if err != nil {
429418
t.Fatalf("UpsertTool failed: %v", err)
430419
}
431420
}
432421
for _, tool := range toolsS2 {
433-
// Capture both return values (using _)
434-
_, err := db.UpsertTool(tool)
422+
err := db.UpsertTool(tool)
435423
if err != nil {
436424
t.Fatalf("UpsertTool failed: %v", err)
437425
}
@@ -483,14 +471,13 @@ func TestRemoveToolsByServerID(t *testing.T) {
483471
servID2, _ := db.AddServer("S2", "http://s2.keep")
484472

485473
// Capture both return values (using _)
486-
_, err := db.UpsertTool(models.Tool{ExternalID: "t1a", SourceServerID: servID1, Name: "Tool A1"})
474+
err := db.UpsertTool(models.Tool{ExternalID: "t1a", SourceServerID: servID1, Name: "Tool A1"})
487475
if err != nil {
488476
t.Fatalf("UpsertTool failed: %v", err)
489477
}
490478

491479
// Add a tool for server 2 as well
492-
// Capture both return values (using _)
493-
_, err = db.UpsertTool(models.Tool{ExternalID: "t2b", SourceServerID: servID2, Name: "Tool B2"})
480+
err = db.UpsertTool(models.Tool{ExternalID: "t2b", SourceServerID: servID2, Name: "Tool B2"})
494481
if err != nil {
495482
t.Fatalf("UpsertTool failed: %v", err)
496483
}
@@ -524,17 +511,17 @@ func TestForeignKey_CascadeDelete(t *testing.T) {
524511
servID2, _ := db.AddServer("ServerToKeep", "http://s2.keep.me")
525512

526513
// Capture both return values (using _)
527-
_, err := db.UpsertTool(models.Tool{ExternalID: "t1a", SourceServerID: servID1, Name: "Tool A1"})
514+
err := db.UpsertTool(models.Tool{ExternalID: "t1a", SourceServerID: servID1, Name: "Tool A1"})
528515
if err != nil {
529516
t.Fatalf("UpsertTool failed: %v", err)
530517
}
531518
// Capture both return values (using _)
532-
_, err = db.UpsertTool(models.Tool{ExternalID: "t1b", SourceServerID: servID1, Name: "Tool B1"})
519+
err = db.UpsertTool(models.Tool{ExternalID: "t1b", SourceServerID: servID1, Name: "Tool B1"})
533520
if err != nil {
534521
t.Fatalf("UpsertTool failed: %v", err)
535522
}
536523
// Capture both return values (using _)
537-
_, err = db.UpsertTool(models.Tool{ExternalID: "t2a", SourceServerID: servID2, Name: "Tool A2"})
524+
err = db.UpsertTool(models.Tool{ExternalID: "t2a", SourceServerID: servID2, Name: "Tool A2"})
538525
if err != nil {
539526
t.Fatalf("UpsertTool failed: %v", err)
540527
}

internal/backend/models/models.go

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,13 @@ type MCPServer struct {
3333

3434
// Tool represents tool metadata fetched from an MCP server and stored in the database.
3535
type Tool struct {
36-
ID int64 `db:"id" json:"id"`
37-
ExternalID string `db:"external_id" json:"external_id"` // Tool ID from the source MCP server
38-
SourceServerID int64 `db:"source_server_id" json:"source_server_id"` // Foreign key to mcp_servers
39-
Name string `db:"name" json:"name"`
40-
Description string `db:"description" json:"description,omitempty"`
41-
// InputSchema json.RawMessage `db:"input_schema" json:"input_schema,omitempty"` // Field removed from DB schema for now
42-
// OutputSchema json.RawMessage `db:"output_schema" json:"output_schema,omitempty"` // Field removed from DB schema for now
43-
// Capabilities json.RawMessage `db:"capabilities" json:"capabilities,omitempty"` // Field removed from DB schema for now
44-
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
45-
CreatedAt time.Time `db:"created_at" json:"created_at"`
36+
ID int64 `db:"id" json:"id"`
37+
ExternalID string `db:"external_id" json:"external_id"` // Tool ID from the source MCP server
38+
SourceServerID int64 `db:"source_server_id" json:"source_server_id"` // Foreign key to mcp_servers
39+
Name string `db:"name" json:"name"`
40+
Description string `db:"description" json:"description,omitempty"`
41+
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
42+
CreatedAt time.Time `db:"created_at" json:"created_at"`
4643
}
4744

4845
// FetchedTool represents the structure of tool data as fetched from an external MCP server's API.
@@ -51,5 +48,4 @@ type FetchedTool struct {
5148
ID string `json:"id"` // External ID
5249
Name string `json:"name"`
5350
Description string `json:"description"`
54-
// Add other fields if the MCP protocol includes them (e.g., InputSchema, OutputSchema)
5551
}

0 commit comments

Comments
 (0)