server

package
v1.12.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2026 License: Apache-2.0 Imports: 100 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// DefaultAsyncPullWorkers bounds how many transfers this node runs at once.
	// Exported because mediorum.go reads it as the env fallback, the way
	// DefaultOpsRetention already is.
	//
	// This is the backpressure that a synchronous pull used to provide by
	// accident: the sender held one of its own workers for the duration, so no
	// node could have more transfers in flight than the sender had workers. A
	// sender that returns immediately can queue as fast as it enumerates, so the
	// limit has to live here, on the side actually moving the bytes.
	//
	// Six rather than the sender's three. Mirroring the sender's worker count
	// was the wrong reference once the limit moved: the receiver is the
	// bottleneck now, and the synchronous handler it replaced ran one goroutine
	// per request with no ceiling at all, so a number chosen to match the
	// sender is a much sharper cut than it looks. Operators tune it with
	// OPENAUDIO_ASYNC_PULL_WORKERS; see MediorumConfig.AsyncPullWorkers.
	DefaultAsyncPullWorkers = 6

	// DefaultAsyncPullTimeout bounds one queued transfer. The request context
	// cannot be used: it is cancelled the moment the handler returns 202.
	//
	// It also bounds how long the source must keep serving the blob. A
	// synchronous pull enforced that structurally -- the sender held the
	// connection, so it knew when the peer was finished reading its bucket.
	// Answering 202 gives that up, so the source's retention is now an
	// invariant nothing checks.
	//
	// It holds today with room to spare. The two paths that delete a blob are
	// guarded by wall clock, not by replication: repair only drops an
	// over-replicated blob whose ModTime is older than a week
	// (wasReplicatedThisWeek), and prune only drops an unpublished upload older
	// than unpublishedUploadAge, 30 days. Either is orders of magnitude beyond
	// this timeout. Tightening one of them below it would break replication
	// silently, since the puller would simply see the object vanish mid
	// transfer.
	DefaultAsyncPullTimeout = 60 * time.Minute
)
View Source
const (
	JobStatusNew     = "new"
	JobStatusError   = "error"
	JobStatusBusy    = "busy"
	JobStatusTimeout = "timeout"

	JobStatusAudioAnalysis     = "audio_analysis"
	JobStatusBusyAudioAnalysis = "busy_audio_analysis"

	JobStatusDone = "done"
)

Job statuses

View Source
const (
	StreamTrack string = "stream_track"
	ServeImage  string = "serve_image"
)

Metric actions

View Source
const (
	DelistStatusPollingInterval              = 20 * time.Second
	HTTPTimeout                              = 5 * time.Minute
	DelistBatchSize                          = 5000
	TimeFormat                               = "2006-01-02 15:04:05.999999-07"
	Tracks                      DelistEntity = "tracks"
	Users                       DelistEntity = "users"
)
View Source
const AUTO = -1
View Source
const DefaultOpsRetention = 30 * 24 * time.Hour
View Source
const DefaultStoreRecentTTL = 365 * 24 * time.Hour
View Source
const (
	MAX_TRIES = 3
)

Variables

View Source
var (
	ErrDiskFull                                 = errors.New("disk is too full to accept new uploads")
	ErrInvalidTemplate                          = errors.New("invalid template")
	ErrUploadToPlacementHosts                   = errors.New("if placement_hosts is specified, you must upload to one of the placement_hosts")
	ErrAllPlacementHostsMustBeRegisteredSigners = errors.New("all placement_hosts must be registered signers")
	ErrInvalidPreviewStartSeconds               = errors.New("invalid preview start seconds")
	ErrUploadProcessFailed                      = errors.New("upload process failed")
)

Functions

func ACAOHeaderOverwriteMiddleware

func ACAOHeaderOverwriteMiddleware(next echo.HandlerFunc) echo.HandlerFunc

func Resized

func Resized(ext string, read io.ReadSeeker, width, height int, mode string) (resized io.ReadSeeker, w int, h int)

Types

type AudioAnalysisResult

type AudioAnalysisResult struct {
	BPM float64 `json:"bpm"`
	Key string  `json:"key"`
}

type AudioPreview

type AudioPreview struct {
	CID                 string `json:"cid" gorm:"primaryKey;column:cid"`
	SourceCID           string
	PreviewStartSeconds string
	CreatedBy           string    `json:"created_by" `
	CreatedAt           time.Time `json:"created_at" gorm:"autoCreateTime:false"`
}

type BlobMetric

type BlobMetric struct {
	Timestamp time.Time `json:"timestamp" gorm:"primaryKey"`
	Count     int64     `json:"count"`
}

type BlobMetrics

type BlobMetrics struct {
	Data []BlobMetric `json:"data"`
}

type BlobPresence added in v1.12.0

type BlobPresence struct {
	Bucket  string    `gorm:"primaryKey;not null"`
	Key     string    `gorm:"primaryKey;not null"`
	Size    int64     `gorm:"not null"`
	ModTime time.Time `gorm:"not null"`
}

BlobPresence records that this node holds Key in Bucket.

Deliberately node-local and NOT registered with crudr: it describes one node's disk, not shared protocol state, and replicating it would tell peers something they must not act on.

Only file:// buckets are tracked. Cloud backends paginate List server-side, so enumerating them is already linear and does not need a durable copy.

func (BlobPresence) TableName added in v1.12.0

func (BlobPresence) TableName() string

type BlobPresenceState added in v1.12.0

type BlobPresenceState struct {
	Bucket   string    `gorm:"primaryKey;not null"`
	WalkedAt time.Time `gorm:"not null"`
	Entries  int64     `gorm:"not null"`
}

BlobPresenceState records that a bucket has been fully enumerated at least once, which is what makes the per-key rows safe to read.

Row count alone cannot answer that. The write path inserts rows as blobs land, so a node that has never walked still accumulates them — and a half-populated table read as authoritative would report most of the corpus missing and send repair off to re-pull all of it.

func (BlobPresenceState) TableName added in v1.12.0

func (BlobPresenceState) TableName() string

type ByteRange

type ByteRange struct {
	Start, End int
}

type ContactResponse

type ContactResponse struct {
	Email string `json:"email"`
}

type DailyMetrics

type DailyMetrics struct {
	Timestamp time.Time `gorm:"primaryKey"`
	Action    string    `gorm:"primaryKey"`
	Count     int64     `gorm:"not null"`
	CreatedAt time.Time `json:"created_at" gorm:"not null"`
}

type DataLossSummary added in v1.9.0

type DataLossSummary struct {
	Total          int64      `json:"total"`
	PendingRecheck int64      `json:"pendingRecheck"`
	Recovered      int64      `json:"recovered"`
	Accumulating   int64      `json:"accumulating"`
	DeclaredLast24 int64      `json:"declaredLast24h"`
	OldestDeclared *time.Time `json:"oldestDeclared,omitempty"`
	NewestDeclared *time.Time `json:"newestDeclared,omitempty"`
}

DataLossSummary is the operator-facing view. Total only grows when a genuinely new CID is declared, so a healthy node reports the same figure indefinitely with zero new losses.

type DelistEntity

type DelistEntity string

type DelistStatus

type DelistStatus struct {
	CreatedAt time.Time `json:"-"`
	Delisted  bool      `json:"delisted"`
	Reason    string    `json:"reason"`

	// fields specific to TrackDelistStatus
	TrackID  int    `json:"trackId,omitempty"`
	TrackCID string `json:"trackCid,omitempty"`
	OwnerID  int    `json:"ownerId,omitempty"`

	// field specific to UserDelistStatus
	UserID int `json:"userId,omitempty"`
}

func (*DelistStatus) UnmarshalJSON

func (ds *DelistStatus) UnmarshalJSON(data []byte) error

type FFProbeResult

type FFProbeResult struct {
	Format struct {
		Filename       string `json:"filename"`
		FormatName     string `json:"format_name"`
		FormatLongName string `json:"format_long_name"`
		Duration       string `json:"duration,omitempty"`
		Size           string `json:"size"`
		BitRate        string `json:"bit_rate,omitempty"`
	} `json:"format"`
}

type FileReader

type FileReader interface {
	Filename() string
	Open() (io.ReadCloser, error)
}

type GeoLocation

type GeoLocation struct {
	Country struct {
		ISOCode string            `maxminddb:"iso_code"`
		Names   map[string]string `maxminddb:"names"`
	} `maxminddb:"country"`
	City struct {
		Names map[string]string `maxminddb:"names"`
	} `maxminddb:"city"`
	Location struct {
		Latitude  float64 `maxminddb:"latitude"`
		Longitude float64 `maxminddb:"longitude"`
	} `maxminddb:"location"`
	Subdivisions []struct {
		ISOCode string            `maxminddb:"iso_code"`
		Names   map[string]string `maxminddb:"names"`
	} `maxminddb:"subdivisions"`
}

type GeoResult

type GeoResult struct {
	Country     string  `json:"country"`
	CountryCode string  `json:"country_code"`
	City        string  `json:"city"`
	Region      string  `json:"region"`
	RegionCode  string  `json:"region_code"`
	Latitude    float64 `json:"latitude"`
	Longitude   float64 `json:"longitude"`
}

type HealthData added in v1.1.1

type HealthData struct {
	Healthy                   bool                       `json:"healthy"`
	Version                   string                     `json:"version"`
	Service                   string                     `json:"service"` // used by registerWithDelegate()
	IsSeeding                 bool                       `json:"isSeeding"`
	IsAudiusdManaged          bool                       `json:"isAudiusdManaged"`
	BuiltAt                   string                     `json:"builtAt"`
	StartedAt                 time.Time                  `json:"startedAt"`
	SPID                      int                        `json:"spID"`
	SPOwnerWallet             string                     `json:"spOwnerWallet"`
	Git                       string                     `json:"git"`
	AudiusDockerCompose       string                     `json:"audiusDockerCompose"`
	MediorumPathUsed          uint64                     `json:"mediorumPathUsed"`   // bytes
	MediorumPathSize          uint64                     `json:"mediorumPathSize"`   // bytes
	StorageExpectation        uint64                     `json:"storageExpectation"` // bytes
	DatabaseSize              uint64                     `json:"databaseSize"`       // bytes
	DbSizeErr                 string                     `json:"dbSizeErr"`
	LastSuccessfulRepair      RepairTracker              `json:"lastSuccessfulRepair"`
	LastSuccessfulCleanup     RepairTracker              `json:"lastSuccessfulCleanup"`
	UploadsCount              int64                      `json:"uploadsCount"`
	UploadsCountErr           string                     `json:"uploadsCountErr"`
	BucketWriteErr            string                     `json:"bucketWriteErr"`
	AutoUpgradeEnabled        bool                       `json:"autoUpgradeEnabled"`
	TrustedNotifier           *ethcontracts.NotifierInfo `json:"trustedNotifier"`
	Env                       string                     `json:"env"`
	Self                      registrar.Peer             `json:"self"`
	WalletIsRegistered        bool                       `json:"wallet_is_registered"`
	Signers                   []registrar.Peer           `json:"signers"`
	ReplicationFactor         int                        `json:"replicationFactor"`
	Dir                       string                     `json:"dir"`
	BlobStorePrefix           string                     `json:"blobStorePrefix"`
	MoveFromBlobStorePrefix   string                     `json:"moveFromBlobStorePrefix"`
	ArchiveStorageConfigured  bool                       `json:"archiveStorageConfigured"`
	ArchiveStoragePrefix      string                     `json:"archiveStoragePrefix"`
	ArchivePathUsed           uint64                     `json:"archivePathUsed"` // bytes
	ArchivePathSize           uint64                     `json:"archivePathSize"` // bytes
	ListenPort                string                     `json:"listenPort"`
	TrustedNotifierID         int                        `json:"trustedNotifierId"`
	PeerHealths               map[string]*PeerHealth     `json:"peerHealths"`
	UnreachablePeers          []string                   `json:"unreachablePeers"`
	FailsPeerReachability     bool                       `json:"failsPeerReachability"`
	StoreAll                  bool                       `json:"storeAll"`
	IsDbLocalhost             bool                       `json:"isDbLocalhost"`
	DiskHasSpace              bool                       `json:"diskHasSpace"`        // aggregate (AND of primary + archive, if archive routes writes)
	PrimaryDiskHasSpace       bool                       `json:"primaryDiskHasSpace"` // primary bucket only
	ArchiveDiskHasSpace       bool                       `json:"archiveDiskHasSpace"` // archive bucket only; false when archive not configured
	IsDiscoveryListensEnabled bool                       `json:"isDiscoveryListensEnabled"`
	TranscodeQueueLength      int                        `json:"transcodeQueueLength"`
	TranscodeStats            *TranscodeStats            `json:"transcodeStats"`
	// PresenceWalk is non-nil only while a presence index walk is running. It
	// is the only external signal that one is in progress: the walk precedes
	// repair's first checkpoint, so /internal/logs/repair still shows the
	// previous run as the latest and has no row for the current one.
	PresenceWalk *PresenceWalkProgress `json:"presenceWalk"`
}

type HostAttrSniff

type HostAttrSniff struct {
	Host           string
	Attr           *blob.Attributes
	RendezvousRank int
}

type JobTemplate

type JobTemplate string

Upload templates

const (
	JobTemplateAudio       JobTemplate = "audio"
	JobTemplateImgSquare   JobTemplate = "img_square"
	JobTemplateImgBackdrop JobTemplate = "img_backdrop"
)

type MediorumConfig

type MediorumConfig struct {
	Env                       string
	Self                      registrar.Peer
	Peers                     []registrar.Peer
	Signers                   []registrar.Peer
	ReplicationFactor         int
	Dir                       string `default:"/tmp/mediorum"`
	BlobStoreDSN              string `json:"-"`
	ArchiveBlobStoreDSN       string `json:"-"`
	MoveFromBlobStoreDSN      string `json:"-"`
	PostgresDSN               string `json:"-"`
	PrivateKey                string `json:"-"`
	ListenPort                string
	TrustedNotifierID         int
	SPID                      int
	SPOwnerWallet             string
	GitSHA                    string
	AudiusDockerCompose       string
	AutoUpgradeEnabled        bool
	WalletIsRegistered        bool
	StoreAll                  bool
	StoreRecent               bool
	StoreRecentTTL            time.Duration `default:"8760h"`
	VersionJson               version.VersionJson
	DiscoveryListensEndpoints []string
	LogLevel                  string
	DeadHosts                 []string
	// PullStagingDir is where an inbound pull buffers a blob before it is
	// validated and committed. Empty means the OS temp dir. Set it when that
	// lives on a smaller filesystem than the blob store -- see pullStagingDir.
	PullStagingDir string
	// AsyncPullWorkers bounds how many inbound transfers this node runs at
	// once. This is the node's replication ingest rate, and the right value is
	// a property of the node -- its bandwidth, its staging disk, and whether it
	// is absorbing a backfill -- so it is tunable rather than fixed.
	//
	// Each concurrent transfer stages a whole blob under PullStagingDir before
	// it is validated, so raising this raises the peak that directory has to
	// hold. That is a sizing consideration for the operator turning it up, not
	// something admission charges every transfer for in advance -- see
	// localDiskReserveBytes.
	AsyncPullWorkers int `default:"6"`
	// AsyncPullTimeout bounds one queued transfer, and with it how long a
	// source must keep serving a blob after answering 202 -- raising it loosens
	// an invariant nothing else checks. See asyncPullTimeout.
	AsyncPullTimeout  time.Duration `default:"60m"`
	RepairEnabled     bool          `default:"true"`
	RepairInterval    time.Duration `default:"1h"`
	RepairConcurrency int           `default:"1"`

	// PresenceStoreEnabled turns on the durable blob_presence store. Off by
	// default: with it off, every repair cycle enumerates its buckets exactly
	// as it did before the store existed, and nothing writes to the table.
	PresenceStoreEnabled bool

	// PresenceWalkConcurrency is how many shard directories the presence index
	// walk visits at once. 1 -- the default -- selects the original serial walk
	// verbatim, so a node that sets nothing behaves exactly as before.
	//
	// Raising it is only worth doing on a bucket large enough for the walk to
	// dominate a repair cycle. The work is one opendir plus one lstat per blob,
	// so it is metadata-latency bound: a serial walk leaves the device at queue
	// depth 1 no matter how many spindles are underneath. 16 is a reasonable
	// setting there. On a raidz vdev every logical read needs all data members,
	// so random-read IOPS is roughly that of a single disk and deeper queues
	// stop helping; on network- or passthrough-backed storage the win is larger
	// but the ceiling is the server's own concurrency.
	PresenceWalkConcurrency int `default:"1"`

	// Waveform analysis is entirely opt-in: all three switches default to
	// false, so a node that sets nothing behaves exactly as before.
	//
	// They nest deliberately, letting an operator walk the cost curve one step
	// at a time -- nothing, then new uploads only, then recent history as
	// well, then the archive tier. Each step is roughly an order of magnitude
	// more expensive than the last, and the last one can mean pulling a
	// multi-terabyte long tail out of cold storage.
	WaveformEnabled         bool
	WaveformBackfillEnabled bool
	WaveformArchiveEnabled  bool
	WaveformWorkers         int `default:"2"`

	// Archive mode (OPENAUDIO_ARCHIVE) keeps all history: no core block pruning
	// and no mediorum op-log pruning. Otherwise ops older than OpsRetention are pruned.
	Archive          bool
	OpsRetention     time.Duration `default:"720h"` // 30 days
	OpsPruneInterval time.Duration `default:"6h"`

	ProgrammableDistributionEnabled bool
	BlobStorageStreaming            bool

	// ContentAuthEnabled is the test override for content authorization when
	// no core is wired. A running node asks core for the rule governing the
	// next block (contentAuthEnabled), so there is no per-node switch to keep
	// in step with the chain.
	ContentAuthEnabled bool
	// contains filtered or unexported fields
}

type MediorumServer

type MediorumServer struct {
	StartedAt time.Time
	Config    MediorumConfig
	// contains filtered or unexported fields
}

func New

func New(lc *lifecycle.Lifecycle, logger *zap.Logger, config MediorumConfig, posChannel chan pos.PoSRequest, core *coreServer.CoreService, ethService ethv1connect.EthServiceHandler) (*MediorumServer, error)

func (*MediorumServer) ApplyMediorumOperation added in v1.6.0

func (ss *MediorumServer) ApplyMediorumOperation(ctx context.Context, msg *corev1.MediorumOperation, txHash string) error

func (*MediorumServer) InvalidateTrackAccessCacheForTrack added in v1.2.3

func (ss *MediorumServer) InvalidateTrackAccessCacheForTrack(trackID string)

InvalidateTrackAccessCacheForTrack removes cached track access info for the given track. Called when management_keys change (gate/ungate). Never fails the caller.

func (*MediorumServer) MustStart

func (ss *MediorumServer) MustStart() error

func (*MediorumServer) Stop

func (ss *MediorumServer) Stop()

type Metrics

type Metrics struct {
	Host              string `json:"host"`
	Uploads           int64  `json:"uploads"`
	RedirectCacheSize int    `json:"redirect_cache_size"`
}

type MonthlyMetrics

type MonthlyMetrics struct {
	Timestamp time.Time `gorm:"primaryKey"`
	Action    string    `gorm:"primaryKey"`
	Count     int64     `gorm:"not null"`
	CreatedAt time.Time `json:"created_at" gorm:"not null"`
}

type PeerHealth

type PeerHealth struct {
	Version        string               `json:"version"`
	LastReachable  time.Time            `json:"lastReachable"`
	LastHealthy    time.Time            `json:"lastHealthy"`
	ReachablePeers map[string]time.Time `json:"reachablePeers"`
	// StoreAll reports whether the peer keeps every CID rather than only its
	// rendezvous share. Such a peer is the best fallback source for a blob the
	// replica set no longer serves, since it holds the whole corpus.
	StoreAll bool `json:"storeAll"`
}

type PlayEvent

type PlayEvent struct {
	RowID            int
	UserID           string
	TrackID          string
	PlayTime         time.Time
	Signature        string
	City             string
	Region           string
	Country          string
	RequestSignature string
}

func (PlayEvent) MarshalLogObject

func (e PlayEvent) MarshalLogObject(enc zapcore.ObjectEncoder) error

Marshal a single PlayEvent

type PlayEventQueue

type PlayEventQueue struct {
	// contains filtered or unexported fields
}

func NewPlayEventQueue

func NewPlayEventQueue() *PlayEventQueue

type PoSResult added in v1.2.14

type PoSResult struct {
	At    time.Time
	CID   string
	OK    bool
	Error string
}

type PresenceWalkProgress added in v1.12.0

type PresenceWalkProgress struct {
	Bucket       string    `json:"bucket"` // "primary" or "archive"
	Dir          string    `json:"dir"`
	Files        int64     `json:"files"`
	Shards       int64     `json:"shards"`
	StartedAt    time.Time `json:"startedAt"`
	ElapsedHuman string    `json:"elapsedHuman"`
	FilesPerSec  float64   `json:"filesPerSec"`
}

PresenceWalkProgress is the health-endpoint view of an in-flight walk. It is null when no walk is running.

This exists because the walk is otherwise invisible: it runs before repair's first checkpoint, so the repair log shows the *previous* run as the latest and there is no tracker row for the current one at all. Without this the only way to distinguish a walking node from a wedged one is a goroutine dump.

type PruneRunStatus added in v1.9.0

type PruneRunStatus struct {
	ID         int64      `json:"id"`
	Task       string     `json:"task"`
	DryRun     bool       `json:"dryRun"`
	StartedAt  time.Time  `json:"startedAt"`
	UpdatedAt  time.Time  `json:"updatedAt"`
	FinishedAt *time.Time `json:"finishedAt"`
	Running    bool       `json:"running"`
	StaleFor   string     `json:"staleFor,omitempty"`
	Scanned    int64      `json:"scanned"`
	Matched    int64      `json:"matched"`
	Removed    int64      `json:"removed"`
	SkipsAdded int64      `json:"skipsAdded"`
	Error      string     `json:"error,omitempty"`
}

PruneRunStatus is one row of prune history. UpdatedAt is the field that matters while a run is in flight: started_at can be hours old on a tree walk, so only the checkpoint age distinguishes progress from a wedged job.

type QmAudioAnalysis

type QmAudioAnalysis struct {
	CID        string               `json:"cid" gorm:"primaryKey;column:cid"`
	Mirrors    []string             `json:"mirrors" gorm:"serializer:json"`
	Status     string               `json:"status"`
	Error      string               `json:"error,omitempty"`
	ErrorCount int                  `json:"error_count"`
	AnalyzedBy string               `json:"analyzed_by"`
	AnalyzedAt time.Time            `json:"analyzed_at"`
	Results    *AudioAnalysisResult `json:"results" gorm:"serializer:json"`
}

type RepairTracker

type RepairTracker struct {
	StartedAt        time.Time `gorm:"primaryKey;not null"`
	UpdatedAt        time.Time `gorm:"not null"`
	FinishedAt       time.Time
	CleanupMode      bool                     `gorm:"not null"`
	CursorI          int                      `gorm:"not null"`
	CursorUploadID   string                   `gorm:"not null"`
	CursorPreviewCID string                   ``
	CursorQmCID      string                   `gorm:"not null"`
	Counters         map[string]int           `gorm:"not null;serializer:json"`
	ContentSize      int64                    `gorm:"not null"`
	Duration         time.Duration            `gorm:"not null"`
	AbortedReason    string                   `gorm:"not null"`
	SeenKeys         map[string]seenKeyResult `gorm:"-" json:"-"`
	// PruneSkips are CIDs repair should not attempt: prune decisions plus
	// declared data loss not yet due for a recheck. Without it an unrecoverable
	// CID is retried on every cycle, forever.
	PruneSkips map[string]struct{} `gorm:"-" json:"-"`
	// HealthyPeerCount is how many peers this run saw. Pull failures from a run
	// that could barely reach the network are not evidence of data loss.
	HealthyPeerCount int `gorm:"-" json:"-"`
	// FailingCIDs maps a CID to how many previous cycles failed to pull it, so
	// the pull path can escalate to a full-network sweep before giving up on
	// it for good. Small by construction: only CIDs that have already failed.
	FailingCIDs map[string]int `gorm:"-" json:"-"`
	// contains filtered or unexported fields
}

type ServedItem added in v1.2.14

type ServedItem struct {
	At     time.Time
	CID    string
	Action string
}

type StorageAndDbSize

type StorageAndDbSize struct {
	LoggedAt           time.Time `gorm:"primaryKey;not null"`
	Host               string    `gorm:"primaryKey;not null"`
	StorageBackend     string    `gorm:"not null"`
	DbUsed             uint64    `gorm:"not null"`
	MediorumDiskUsed   uint64    `gorm:"not null"`
	MediorumDiskSize   uint64    `gorm:"not null"`
	StorageExpectation uint64    `gorm:"not null;default:0"`
	LastRepairSize     int64     `gorm:"not null"`
	LastCleanupSize    int64     `gorm:"not null"`
}

type StorageService

type StorageService struct {
	// contains filtered or unexported fields
}

func NewStorageService

func NewStorageService() *StorageService

func (*StorageService) ApplyMediorumOperation added in v1.6.0

func (s *StorageService) ApplyMediorumOperation(ctx context.Context, msg *corev1.MediorumOperation, txHash string) error

func (*StorageService) GetHealth

GetHealth implements v1connect.StorageServiceHandler.

func (*StorageService) GetIPData

GetIPData implements v1connect.StorageServiceHandler.

func (*StorageService) GetMediorumHealth added in v1.1.1

func (s *StorageService) GetMediorumHealth() (HealthData, error)

GetMediorumHealth returns the health check data for the mediorum process

func (*StorageService) GetRendezvousNodes

GetRendezvousNodes implements v1connect.StorageServiceHandler.

func (*StorageService) GetStatus

GetStatus implements v1connect.StorageServiceHandler.

func (*StorageService) GetStorageDiagnostics added in v1.2.14

GetStorageDiagnostics implements v1connect.StorageServiceHandler.

func (*StorageService) GetStreamURL

GetStreamURL implements v1connect.StorageServiceHandler.

func (*StorageService) GetUpload

GetUpload implements v1connect.StorageServiceHandler.

func (*StorageService) InvalidateTrackAccessCacheForTrack added in v1.2.3

func (s *StorageService) InvalidateTrackAccessCacheForTrack(trackID string)

InvalidateTrackAccessCacheForTrack clears cached track access info when management_keys change.

func (*StorageService) Ping

Ping implements v1connect.StorageServiceHandler.

func (*StorageService) SetMediorum

func (s *StorageService) SetMediorum(mediorum *MediorumServer)

func (*StorageService) StreamTrack

StreamTrack implements v1connect.StorageServiceHandler.

func (*StorageService) UploadFiles

UploadFiles implements v1connect.StorageServiceHandler.

type TranscodeStats

type TranscodeStats struct {
	Since              time.Time `db:"since"`
	UploadCount        int       `db:"upload_count"`
	MinTranscodeTime   float64   `db:"min_transcode_time"`
	AvgTranscodeTime   float64   `db:"avg_transcode_time"`
	MaxTranscodeTime   float64   `db:"max_transcode_time"`
	TotalTranscodeTime float64   `db:"total_transcode_time"`
	TotalBytes         int       `db:"total_bytes"`
	TranscodeRate      float64   `db:"transcode_rate"`
}

type UpdateUploadBody

type UpdateUploadBody struct {
	PreviewStartSeconds string `json:"previewStartSeconds"`
}

type Upload

type Upload struct {
	ID string `json:"id"` // base32 file hash

	// UserWallet is populated only by the legacy POST /uploads and gRPC paths,
	// from an unverified X-User-Wallet-Addr header. It plays no part in
	// attestation; the tus path leaves it null.
	UserWallet sql.NullString `json:"user_wallet"`
	// UserID is the user this upload was made for, asserted in tus metadata.
	// An assertion, not proof — see upload_auth.go for why that is safe and
	// for the constraint it puts on how claims may be interpreted.
	UserID            sql.NullInt64  `json:"user_id"`
	Template          JobTemplate    `json:"template"`
	OrigFileName      string         `json:"orig_filename"`
	OrigFileCID       string         `json:"orig_file_cid" gorm:"column:orig_file_cid;index:idx_uploads_orig_file_cid"` //
	SelectedPreview   sql.NullString `json:"selected_preview"`
	FFProbe           *FFProbeResult `json:"probe" gorm:"serializer:json"`
	Error             string         `json:"error,omitempty"`
	ErrorCount        int            `json:"error_count,omitempty"`
	Mirrors           []string       `json:"mirrors" gorm:"serializer:json"`
	TranscodedMirrors []string       `json:"transcoded_mirrors" gorm:"serializer:json"`
	Status            string         `json:"status" gorm:"index"`
	PlacementHosts    []string       `json:"placement_hosts" gorm:"serializer:json"`

	CreatedBy string    `json:"created_by" `
	CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime:false"`
	UpdatedAt time.Time `json:"updated_at" gorm:"autoCreateTime:false"`

	TranscodedBy      string            `json:"transcoded_by"`
	TranscodeProgress float64           `json:"transcode_progress"`
	TranscodedAt      time.Time         `json:"transcoded_at"`
	TranscodeResults  map[string]string `json:"results" gorm:"serializer:json"`

	AudioAnalysisStatus     string               `json:"audio_analysis_status"`
	AudioAnalysisError      string               `json:"audio_analysis_error,omitempty"`
	AudioAnalysisErrorCount int                  `json:"audio_analysis_error_count"`
	AudioAnalyzedBy         string               `json:"audio_analyzed_by"`
	AudioAnalyzedAt         time.Time            `json:"audio_analyzed_at"`
	AudioAnalysisResults    *AudioAnalysisResult `json:"audio_analysis_results" gorm:"serializer:json"`
}

type UploadCursor

type UploadCursor struct {
	Host  string `gorm:"primaryKey"`
	After time.Time
}

UploadCursor tracks how far the upload scroller has walked each peer's created_at-ordered upload history. See startUploadScroller.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL