Fork channel

Create a new channel as a copy of main.

Rename channel

Rename main to:

Delete channel

Delete main? This cannot be undone.

file_import.go
package imp

import (
	"context"
	"database/sql"
	"fmt"
)

// ImportStage identifies the pipeline stage where an error occurred.
type ImportStage string

const (
	StageScan       ImportStage = "scan"       // directory scanning
	StageHash       ImportStage = "hash"       // hash computation
	StageParse      ImportStage = "parse"      // WAV header / filename parsing
	StageProcess    ImportStage = "process"    // file processing
	StageValidation ImportStage = "validation" // validation checks
	StageInsert     ImportStage = "insert"     // database insertion
	StageImport     ImportStage = "import"     // database import (segment pipeline)
)

// FileImportError records errors encountered during file processing
type FileImportError struct {
	FileName string      `json:"file_name"`
	Error    string      `json:"error"`
	Stage    ImportStage `json:"stage"`
}

// CheckDuplicateHash checks if a file with the given XXH64 hash already exists.
// Returns the existing file ID if found, or empty string if no duplicate.
// Works with both *sql.DB, *sql.Tx, and *db.LoggedTx.
func CheckDuplicateHash(q interface {
	QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
}, hash string) (existingID string, isDuplicate bool, err error) {
	err = q.QueryRowContext(context.Background(),
		"SELECT id FROM file WHERE xxh64_hash = ? AND active = true",
		hash,
	).Scan(&existingID)

	if err == nil {
		return existingID, true, nil
	}
	if err == sql.ErrNoRows {
		return "", false, nil
	}
	return "", false, fmt.Errorf("duplicate check failed: %w", err)
}