MarkUninstalled removes the specified app from the installed targets list. If no targets remain, the installed flag is cleared. Uses a transaction to prevent race conditions when multiple concurrent uninstalls target the same item.
(ctx context.Context, kind, installKey, app string)
| 315 | // If no targets remain, the installed flag is cleared. Uses a transaction to |
| 316 | // prevent race conditions when multiple concurrent uninstalls target the same item. |
| 317 | func (s *Store) MarkUninstalled(ctx context.Context, kind, installKey, app string) error { |
| 318 | if err := s.Init(ctx); err != nil { |
| 319 | return err |
| 320 | } |
| 321 | db, err := s.open() |
| 322 | if err != nil { |
| 323 | return err |
| 324 | } |
| 325 | defer db.Close() |
| 326 | tx, err := db.BeginTx(ctx, nil) |
| 327 | if err != nil { |
| 328 | return fmt.Errorf("metadata: mark uninstalled: begin tx: %w", err) |
| 329 | } |
| 330 | defer tx.Rollback() |
| 331 | // Fetch current targets within the transaction. |
| 332 | var currentTargets string |
| 333 | err = tx.QueryRowContext(ctx, ` |
| 334 | SELECT installed_targets FROM metadata_items |
| 335 | WHERE kind = ? AND install_key = ?`, kind, installKey).Scan(¤tTargets) |
| 336 | if err != nil { |
| 337 | return fmt.Errorf("metadata: mark uninstalled: %w", err) |
| 338 | } |
| 339 | // Remove the app from the comma-separated list. |
| 340 | newTargets := removeAppFromTargets(currentTargets, app) |
| 341 | now := timeNow() |
| 342 | if newTargets == "" { |
| 343 | _, err = tx.ExecContext(ctx, ` |
| 344 | UPDATE metadata_items SET installed = 0, installed_targets = '', updated_at = ? |
| 345 | WHERE kind = ? AND install_key = ?`, now, kind, installKey) |
| 346 | } else { |
| 347 | _, err = tx.ExecContext(ctx, ` |
| 348 | UPDATE metadata_items SET installed_targets = ?, updated_at = ? |
| 349 | WHERE kind = ? AND install_key = ?`, newTargets, now, kind, installKey) |
| 350 | } |
| 351 | if err != nil { |
| 352 | return fmt.Errorf("metadata: mark uninstalled: %w", err) |
| 353 | } |
| 354 | return tx.Commit() |
| 355 | } |
| 356 | |
| 357 | // removeAppFromTargets removes a specific app from a comma-separated target list. |
| 358 | func removeAppFromTargets(targets, app string) string { |
no test coverage detected