mirror of
https://github.com/cloudreve/cloudreve.git
synced 2025-10-31 00:27:31 +08:00
Init V4 community edition (#2265)
* Init V4 community edition * Init V4 community edition
This commit is contained in:
874
application/dependency/dependency.go
Normal file
874
application/dependency/dependency.go
Normal file
@ -0,0 +1,874 @@
|
||||
package dependency
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
iofs "io/fs"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/cloudreve/Cloudreve/v4/application/statics"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent"
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/auth"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/cache"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/cluster"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/conf"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/credmanager"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/email"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs/mime"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/lock"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/hashid"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/logging"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/mediameta"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/queue"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/request"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/setting"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/thumb"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/util"
|
||||
"github.com/gin-contrib/static"
|
||||
"github.com/go-webauthn/webauthn/webauthn"
|
||||
"github.com/robfig/cron/v3"
|
||||
"github.com/samber/lo"
|
||||
"github.com/ua-parser/uap-go/uaparser"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrorConfigPathNotSet = errors.New("config path not set")
|
||||
)
|
||||
|
||||
type (
|
||||
// DepCtx defines keys for dependency manager
|
||||
DepCtx struct{}
|
||||
// ReloadCtx force reload new dependency
|
||||
ReloadCtx struct{}
|
||||
)
|
||||
|
||||
// Dep manages all dependencies of the server application. The default implementation is not
|
||||
// concurrent safe, so all inner deps should be initialized before any goroutine starts.
|
||||
type Dep interface {
|
||||
// ConfigProvider Get a singleton conf.ConfigProvider instance.
|
||||
ConfigProvider() conf.ConfigProvider
|
||||
// Logger Get a singleton logging.Logger instance.
|
||||
Logger() logging.Logger
|
||||
// Statics Get a singleton fs.FS instance for embedded static resources.
|
||||
Statics() iofs.FS
|
||||
// ServerStaticFS Get a singleton static.ServeFileSystem instance for serving static resources.
|
||||
ServerStaticFS() static.ServeFileSystem
|
||||
// DBClient Get a singleton ent.Client instance for database access.
|
||||
DBClient() *ent.Client
|
||||
// KV Get a singleton cache.Driver instance for KV store.
|
||||
KV() cache.Driver
|
||||
// NavigatorStateKV Get a singleton cache.Driver instance for navigator state store. It forces use in-memory
|
||||
// map instead of Redis to get better performance for complex nested linked list.
|
||||
NavigatorStateKV() cache.Driver
|
||||
// SettingClient Get a singleton inventory.SettingClient instance for access DB setting store.
|
||||
SettingClient() inventory.SettingClient
|
||||
// SettingProvider Get a singleton setting.Provider instance for access setting store in strong type.
|
||||
SettingProvider() setting.Provider
|
||||
// UserClient Creates a new inventory.UserClient instance for access DB user store.
|
||||
UserClient() inventory.UserClient
|
||||
// GroupClient Creates a new inventory.GroupClient instance for access DB group store.
|
||||
GroupClient() inventory.GroupClient
|
||||
// EmailClient Get a singleton email.Driver instance for sending emails.
|
||||
EmailClient(ctx context.Context) email.Driver
|
||||
// GeneralAuth Get a singleton auth.Auth instance for general authentication.
|
||||
GeneralAuth() auth.Auth
|
||||
// Shutdown the dependencies gracefully.
|
||||
Shutdown(ctx context.Context) error
|
||||
// FileClient Creates a new inventory.FileClient instance for access DB file store.
|
||||
FileClient() inventory.FileClient
|
||||
// NodeClient Creates a new inventory.NodeClient instance for access DB node store.
|
||||
NodeClient() inventory.NodeClient
|
||||
// DavAccountClient Creates a new inventory.DavAccountClient instance for access DB dav account store.
|
||||
DavAccountClient() inventory.DavAccountClient
|
||||
// DirectLinkClient Creates a new inventory.DirectLinkClient instance for access DB direct link store.
|
||||
DirectLinkClient() inventory.DirectLinkClient
|
||||
// HashIDEncoder Get a singleton hashid.Encoder instance for encoding/decoding hashids.
|
||||
HashIDEncoder() hashid.Encoder
|
||||
// TokenAuth Get a singleton auth.TokenAuth instance for token authentication.
|
||||
TokenAuth() auth.TokenAuth
|
||||
// LockSystem Get a singleton lock.LockSystem instance for file lock management.
|
||||
LockSystem() lock.LockSystem
|
||||
// ShareClient Creates a new inventory.ShareClient instance for access DB share store.
|
||||
StoragePolicyClient() inventory.StoragePolicyClient
|
||||
// RequestClient Creates a new request.Client instance for HTTP requests.
|
||||
RequestClient(opts ...request.Option) request.Client
|
||||
// ShareClient Creates a new inventory.ShareClient instance for access DB share store.
|
||||
ShareClient() inventory.ShareClient
|
||||
// TaskClient Creates a new inventory.TaskClient instance for access DB task store.
|
||||
TaskClient() inventory.TaskClient
|
||||
// ForkWithLogger create a shallow copy of dependency with a new correlated logger, used as per-request dep.
|
||||
ForkWithLogger(ctx context.Context, l logging.Logger) context.Context
|
||||
// MediaMetaQueue Get a singleton queue.Queue instance for media metadata processing.
|
||||
MediaMetaQueue(ctx context.Context) queue.Queue
|
||||
// SlaveQueue Get a singleton queue.Queue instance for slave tasks.
|
||||
SlaveQueue(ctx context.Context) queue.Queue
|
||||
// MediaMetaExtractor Get a singleton mediameta.Extractor instance for media metadata extraction.
|
||||
MediaMetaExtractor(ctx context.Context) mediameta.Extractor
|
||||
// ThumbPipeline Get a singleton thumb.Generator instance for chained thumbnail generation.
|
||||
ThumbPipeline() thumb.Generator
|
||||
// ThumbQueue Get a singleton queue.Queue instance for thumbnail generation.
|
||||
ThumbQueue(ctx context.Context) queue.Queue
|
||||
// EntityRecycleQueue Get a singleton queue.Queue instance for entity recycle.
|
||||
EntityRecycleQueue(ctx context.Context) queue.Queue
|
||||
// MimeDetector Get a singleton fs.MimeDetector instance for MIME type detection.
|
||||
MimeDetector(ctx context.Context) mime.MimeDetector
|
||||
// CredManager Get a singleton credmanager.CredManager instance for credential management.
|
||||
CredManager() credmanager.CredManager
|
||||
// IoIntenseQueue Get a singleton queue.Queue instance for IO intense tasks.
|
||||
IoIntenseQueue(ctx context.Context) queue.Queue
|
||||
// RemoteDownloadQueue Get a singleton queue.Queue instance for remote download tasks.
|
||||
RemoteDownloadQueue(ctx context.Context) queue.Queue
|
||||
// NodePool Get a singleton cluster.NodePool instance for node pool management.
|
||||
NodePool(ctx context.Context) (cluster.NodePool, error)
|
||||
// TaskRegistry Get a singleton queue.TaskRegistry instance for task registration.
|
||||
TaskRegistry() queue.TaskRegistry
|
||||
// WebAuthn Get a singleton webauthn.WebAuthn instance for WebAuthn authentication.
|
||||
WebAuthn(ctx context.Context) (*webauthn.WebAuthn, error)
|
||||
// UAParser Get a singleton uaparser.Parser instance for user agent parsing.
|
||||
UAParser() *uaparser.Parser
|
||||
}
|
||||
|
||||
type dependency struct {
|
||||
configProvider conf.ConfigProvider
|
||||
logger logging.Logger
|
||||
statics iofs.FS
|
||||
serverStaticFS static.ServeFileSystem
|
||||
dbClient *ent.Client
|
||||
rawEntClient *ent.Client
|
||||
kv cache.Driver
|
||||
navigatorStateKv cache.Driver
|
||||
settingClient inventory.SettingClient
|
||||
fileClient inventory.FileClient
|
||||
shareClient inventory.ShareClient
|
||||
settingProvider setting.Provider
|
||||
userClient inventory.UserClient
|
||||
groupClient inventory.GroupClient
|
||||
storagePolicyClient inventory.StoragePolicyClient
|
||||
taskClient inventory.TaskClient
|
||||
nodeClient inventory.NodeClient
|
||||
davAccountClient inventory.DavAccountClient
|
||||
directLinkClient inventory.DirectLinkClient
|
||||
emailClient email.Driver
|
||||
generalAuth auth.Auth
|
||||
hashidEncoder hashid.Encoder
|
||||
tokenAuth auth.TokenAuth
|
||||
lockSystem lock.LockSystem
|
||||
requestClient request.Client
|
||||
ioIntenseQueue queue.Queue
|
||||
thumbQueue queue.Queue
|
||||
mediaMetaQueue queue.Queue
|
||||
entityRecycleQueue queue.Queue
|
||||
slaveQueue queue.Queue
|
||||
remoteDownloadQueue queue.Queue
|
||||
ioIntenseQueueTask queue.Task
|
||||
mediaMeta mediameta.Extractor
|
||||
thumbPipeline thumb.Generator
|
||||
mimeDetector mime.MimeDetector
|
||||
credManager credmanager.CredManager
|
||||
nodePool cluster.NodePool
|
||||
taskRegistry queue.TaskRegistry
|
||||
webauthn *webauthn.WebAuthn
|
||||
parser *uaparser.Parser
|
||||
cron *cron.Cron
|
||||
|
||||
configPath string
|
||||
isPro bool
|
||||
requiredDbVersion string
|
||||
licenseKey string
|
||||
|
||||
// Protects inner deps that can be reloaded at runtime.
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// NewDependency creates a new Dep instance for construct dependencies.
|
||||
func NewDependency(opts ...Option) Dep {
|
||||
d := &dependency{}
|
||||
for _, o := range opts {
|
||||
o.apply(d)
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
// FromContext retrieves a Dep instance from context.
|
||||
func FromContext(ctx context.Context) Dep {
|
||||
return ctx.Value(DepCtx{}).(Dep)
|
||||
}
|
||||
|
||||
func (d *dependency) RequestClient(opts ...request.Option) request.Client {
|
||||
if d.requestClient != nil {
|
||||
return d.requestClient
|
||||
}
|
||||
|
||||
return request.NewClient(d.ConfigProvider(), opts...)
|
||||
}
|
||||
|
||||
func (d *dependency) WebAuthn(ctx context.Context) (*webauthn.WebAuthn, error) {
|
||||
if d.webauthn != nil {
|
||||
return d.webauthn, nil
|
||||
}
|
||||
|
||||
settings := d.SettingProvider()
|
||||
siteBasic := settings.SiteBasic(ctx)
|
||||
wConfig := &webauthn.Config{
|
||||
RPDisplayName: siteBasic.Name,
|
||||
RPID: settings.SiteURL(ctx).Hostname(),
|
||||
RPOrigins: lo.Map(settings.AllSiteURLs(ctx), func(item *url.URL, index int) string {
|
||||
item.Path = ""
|
||||
return item.String()
|
||||
}), // The origin URLs allowed for WebAuthn requests
|
||||
}
|
||||
|
||||
return webauthn.New(wConfig)
|
||||
}
|
||||
|
||||
func (d *dependency) UAParser() *uaparser.Parser {
|
||||
if d.parser != nil {
|
||||
return d.parser
|
||||
}
|
||||
|
||||
d.parser = uaparser.NewFromSaved()
|
||||
return d.parser
|
||||
}
|
||||
|
||||
func (d *dependency) ConfigProvider() conf.ConfigProvider {
|
||||
if d.configProvider != nil {
|
||||
return d.configProvider
|
||||
}
|
||||
|
||||
if d.configPath == "" {
|
||||
d.panicError(ErrorConfigPathNotSet)
|
||||
}
|
||||
|
||||
var err error
|
||||
d.configProvider, err = conf.NewIniConfigProvider(d.configPath, logging.NewConsoleLogger(logging.LevelInformational))
|
||||
if err != nil {
|
||||
d.panicError(err)
|
||||
}
|
||||
|
||||
return d.configProvider
|
||||
}
|
||||
|
||||
func (d *dependency) Logger() logging.Logger {
|
||||
if d.logger != nil {
|
||||
return d.logger
|
||||
}
|
||||
|
||||
config := d.ConfigProvider()
|
||||
logLevel := logging.LogLevel(config.System().LogLevel)
|
||||
if config.System().Debug {
|
||||
logLevel = logging.LevelDebug
|
||||
}
|
||||
|
||||
d.logger = logging.NewConsoleLogger(logLevel)
|
||||
d.logger.Info("Logger initialized with LogLevel=%q.", logLevel)
|
||||
return d.logger
|
||||
}
|
||||
|
||||
func (d *dependency) Statics() iofs.FS {
|
||||
if d.statics != nil {
|
||||
return d.statics
|
||||
}
|
||||
|
||||
d.statics = statics.NewStaticFS(d.Logger())
|
||||
return d.statics
|
||||
}
|
||||
|
||||
func (d *dependency) ServerStaticFS() static.ServeFileSystem {
|
||||
if d.serverStaticFS != nil {
|
||||
return d.serverStaticFS
|
||||
}
|
||||
|
||||
sfs, err := statics.NewServerStaticFS(d.Logger(), d.Statics(), d.isPro)
|
||||
if err != nil {
|
||||
d.panicError(err)
|
||||
}
|
||||
|
||||
d.serverStaticFS = sfs
|
||||
return d.serverStaticFS
|
||||
}
|
||||
|
||||
func (d *dependency) DBClient() *ent.Client {
|
||||
if d.dbClient != nil {
|
||||
return d.dbClient
|
||||
}
|
||||
|
||||
if d.rawEntClient == nil {
|
||||
client, err := inventory.NewRawEntClient(d.Logger(), d.ConfigProvider())
|
||||
if err != nil {
|
||||
d.panicError(err)
|
||||
}
|
||||
|
||||
d.rawEntClient = client
|
||||
}
|
||||
|
||||
client, err := inventory.InitializeDBClient(d.Logger(), d.rawEntClient, d.KV(), d.requiredDbVersion)
|
||||
if err != nil {
|
||||
d.panicError(err)
|
||||
}
|
||||
|
||||
d.dbClient = client
|
||||
return d.dbClient
|
||||
}
|
||||
|
||||
func (d *dependency) KV() cache.Driver {
|
||||
if d.kv != nil {
|
||||
return d.kv
|
||||
}
|
||||
|
||||
config := d.ConfigProvider().Redis()
|
||||
if config.Server != "" {
|
||||
d.kv = cache.NewRedisStore(
|
||||
d.Logger(),
|
||||
10,
|
||||
config.Network,
|
||||
config.Server,
|
||||
config.User,
|
||||
config.Password,
|
||||
config.DB,
|
||||
)
|
||||
} else {
|
||||
d.kv = cache.NewMemoStore(util.DataPath(cache.DefaultCacheFile), d.Logger())
|
||||
}
|
||||
|
||||
return d.kv
|
||||
}
|
||||
|
||||
func (d *dependency) NavigatorStateKV() cache.Driver {
|
||||
if d.navigatorStateKv != nil {
|
||||
return d.navigatorStateKv
|
||||
}
|
||||
d.navigatorStateKv = cache.NewMemoStore("", d.Logger())
|
||||
return d.navigatorStateKv
|
||||
}
|
||||
|
||||
func (d *dependency) SettingClient() inventory.SettingClient {
|
||||
if d.settingClient != nil {
|
||||
return d.settingClient
|
||||
}
|
||||
|
||||
d.settingClient = inventory.NewSettingClient(d.DBClient(), d.KV())
|
||||
return d.settingClient
|
||||
}
|
||||
|
||||
func (d *dependency) SettingProvider() setting.Provider {
|
||||
if d.settingProvider != nil {
|
||||
return d.settingProvider
|
||||
}
|
||||
|
||||
if d.ConfigProvider().System().Mode == conf.MasterMode {
|
||||
// For master mode, setting value will be retrieved in order:
|
||||
// Env overwrite -> KV Store -> DB Setting Store
|
||||
d.settingProvider = setting.NewProvider(
|
||||
setting.NewEnvOverrideStore(
|
||||
setting.NewKvSettingStore(d.KV(),
|
||||
setting.NewDbSettingStore(d.SettingClient(), nil),
|
||||
),
|
||||
d.Logger(),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
// For slave mode, setting value will be retrieved in order:
|
||||
// Env overwrite -> Config file overwrites -> Setting defaults in DB schema
|
||||
d.settingProvider = setting.NewProvider(
|
||||
setting.NewEnvOverrideStore(
|
||||
setting.NewConfSettingStore(d.ConfigProvider(),
|
||||
setting.NewDbDefaultStore(nil),
|
||||
),
|
||||
d.Logger(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return d.settingProvider
|
||||
}
|
||||
|
||||
func (d *dependency) UserClient() inventory.UserClient {
|
||||
if d.userClient != nil {
|
||||
return d.userClient
|
||||
}
|
||||
|
||||
return inventory.NewUserClient(d.DBClient())
|
||||
}
|
||||
|
||||
func (d *dependency) GroupClient() inventory.GroupClient {
|
||||
if d.groupClient != nil {
|
||||
return d.groupClient
|
||||
}
|
||||
|
||||
return inventory.NewGroupClient(d.DBClient(), d.ConfigProvider().Database().Type, d.KV())
|
||||
}
|
||||
|
||||
func (d *dependency) NodeClient() inventory.NodeClient {
|
||||
if d.nodeClient != nil {
|
||||
return d.nodeClient
|
||||
}
|
||||
|
||||
return inventory.NewNodeClient(d.DBClient())
|
||||
}
|
||||
|
||||
func (d *dependency) NodePool(ctx context.Context) (cluster.NodePool, error) {
|
||||
reload, _ := ctx.Value(ReloadCtx{}).(bool)
|
||||
if d.nodePool != nil && !reload {
|
||||
return d.nodePool, nil
|
||||
}
|
||||
|
||||
if d.ConfigProvider().System().Mode == conf.MasterMode {
|
||||
np, err := cluster.NewNodePool(ctx, d.Logger(), d.ConfigProvider(), d.SettingProvider(), d.NodeClient())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.nodePool = np
|
||||
} else {
|
||||
d.nodePool = cluster.NewSlaveDummyNodePool(ctx, d.ConfigProvider(), d.SettingProvider())
|
||||
}
|
||||
|
||||
return d.nodePool, nil
|
||||
}
|
||||
|
||||
func (d *dependency) EmailClient(ctx context.Context) email.Driver {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
if reload, _ := ctx.Value(ReloadCtx{}).(bool); reload || d.emailClient == nil {
|
||||
if d.emailClient != nil {
|
||||
d.emailClient.Close()
|
||||
}
|
||||
d.emailClient = email.NewSMTPPool(d.SettingProvider(), d.Logger())
|
||||
}
|
||||
|
||||
return d.emailClient
|
||||
}
|
||||
|
||||
func (d *dependency) MimeDetector(ctx context.Context) mime.MimeDetector {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
_, reload := ctx.Value(ReloadCtx{}).(bool)
|
||||
if d.mimeDetector != nil && !reload {
|
||||
return d.mimeDetector
|
||||
}
|
||||
|
||||
d.mimeDetector = mime.NewMimeDetector(ctx, d.SettingProvider(), d.Logger())
|
||||
return d.mimeDetector
|
||||
}
|
||||
|
||||
func (d *dependency) MediaMetaExtractor(ctx context.Context) mediameta.Extractor {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
_, reload := ctx.Value(ReloadCtx{}).(bool)
|
||||
if d.mediaMeta != nil && !reload {
|
||||
return d.mediaMeta
|
||||
}
|
||||
|
||||
d.mediaMeta = mediameta.NewExtractorManager(ctx, d.SettingProvider(), d.Logger())
|
||||
return d.mediaMeta
|
||||
}
|
||||
|
||||
func (d *dependency) ThumbQueue(ctx context.Context) queue.Queue {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
_, reload := ctx.Value(ReloadCtx{}).(bool)
|
||||
if d.thumbQueue != nil && !reload {
|
||||
return d.thumbQueue
|
||||
}
|
||||
|
||||
if d.thumbQueue != nil {
|
||||
d.thumbQueue.Shutdown()
|
||||
}
|
||||
|
||||
settings := d.SettingProvider()
|
||||
queueSetting := settings.Queue(context.Background(), setting.QueueTypeThumb)
|
||||
var (
|
||||
t inventory.TaskClient
|
||||
)
|
||||
if d.ConfigProvider().System().Mode == conf.MasterMode {
|
||||
t = d.TaskClient()
|
||||
}
|
||||
|
||||
d.thumbQueue = queue.New(d.Logger(), t, nil, d,
|
||||
queue.WithBackoffFactor(queueSetting.BackoffFactor),
|
||||
queue.WithMaxRetry(queueSetting.MaxRetry),
|
||||
queue.WithBackoffMaxDuration(queueSetting.BackoffMaxDuration),
|
||||
queue.WithRetryDelay(queueSetting.RetryDelay),
|
||||
queue.WithWorkerCount(queueSetting.WorkerNum),
|
||||
queue.WithName("ThumbQueue"),
|
||||
queue.WithMaxTaskExecution(queueSetting.MaxExecution),
|
||||
)
|
||||
return d.thumbQueue
|
||||
}
|
||||
|
||||
func (d *dependency) MediaMetaQueue(ctx context.Context) queue.Queue {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
_, reload := ctx.Value(ReloadCtx{}).(bool)
|
||||
if d.mediaMetaQueue != nil && !reload {
|
||||
return d.mediaMetaQueue
|
||||
}
|
||||
|
||||
if d.mediaMetaQueue != nil {
|
||||
d.mediaMetaQueue.Shutdown()
|
||||
}
|
||||
|
||||
settings := d.SettingProvider()
|
||||
queueSetting := settings.Queue(context.Background(), setting.QueueTypeMediaMeta)
|
||||
|
||||
d.mediaMetaQueue = queue.New(d.Logger(), d.TaskClient(), nil, d,
|
||||
queue.WithBackoffFactor(queueSetting.BackoffFactor),
|
||||
queue.WithMaxRetry(queueSetting.MaxRetry),
|
||||
queue.WithBackoffMaxDuration(queueSetting.BackoffMaxDuration),
|
||||
queue.WithRetryDelay(queueSetting.RetryDelay),
|
||||
queue.WithWorkerCount(queueSetting.WorkerNum),
|
||||
queue.WithName("MediaMetadataQueue"),
|
||||
queue.WithMaxTaskExecution(queueSetting.MaxExecution),
|
||||
queue.WithResumeTaskType(queue.MediaMetaTaskType),
|
||||
)
|
||||
return d.mediaMetaQueue
|
||||
}
|
||||
|
||||
func (d *dependency) IoIntenseQueue(ctx context.Context) queue.Queue {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
_, reload := ctx.Value(ReloadCtx{}).(bool)
|
||||
if d.ioIntenseQueue != nil && !reload {
|
||||
return d.ioIntenseQueue
|
||||
}
|
||||
|
||||
if d.ioIntenseQueue != nil {
|
||||
d.ioIntenseQueue.Shutdown()
|
||||
}
|
||||
|
||||
settings := d.SettingProvider()
|
||||
queueSetting := settings.Queue(context.Background(), setting.QueueTypeIOIntense)
|
||||
|
||||
d.ioIntenseQueue = queue.New(d.Logger(), d.TaskClient(), d.TaskRegistry(), d,
|
||||
queue.WithBackoffFactor(queueSetting.BackoffFactor),
|
||||
queue.WithMaxRetry(queueSetting.MaxRetry),
|
||||
queue.WithBackoffMaxDuration(queueSetting.BackoffMaxDuration),
|
||||
queue.WithRetryDelay(queueSetting.RetryDelay),
|
||||
queue.WithWorkerCount(queueSetting.WorkerNum),
|
||||
queue.WithName("IoIntenseQueue"),
|
||||
queue.WithMaxTaskExecution(queueSetting.MaxExecution),
|
||||
queue.WithResumeTaskType(queue.CreateArchiveTaskType, queue.ExtractArchiveTaskType, queue.RelocateTaskType),
|
||||
queue.WithTaskPullInterval(10*time.Second),
|
||||
)
|
||||
return d.ioIntenseQueue
|
||||
}
|
||||
|
||||
func (d *dependency) RemoteDownloadQueue(ctx context.Context) queue.Queue {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
_, reload := ctx.Value(ReloadCtx{}).(bool)
|
||||
if d.remoteDownloadQueue != nil && !reload {
|
||||
return d.remoteDownloadQueue
|
||||
}
|
||||
|
||||
if d.remoteDownloadQueue != nil {
|
||||
d.remoteDownloadQueue.Shutdown()
|
||||
}
|
||||
|
||||
settings := d.SettingProvider()
|
||||
queueSetting := settings.Queue(context.Background(), setting.QueueTypeRemoteDownload)
|
||||
|
||||
d.remoteDownloadQueue = queue.New(d.Logger(), d.TaskClient(), d.TaskRegistry(), d,
|
||||
queue.WithBackoffFactor(queueSetting.BackoffFactor),
|
||||
queue.WithMaxRetry(queueSetting.MaxRetry),
|
||||
queue.WithBackoffMaxDuration(queueSetting.BackoffMaxDuration),
|
||||
queue.WithRetryDelay(queueSetting.RetryDelay),
|
||||
queue.WithWorkerCount(queueSetting.WorkerNum),
|
||||
queue.WithName("RemoteDownloadQueue"),
|
||||
queue.WithMaxTaskExecution(queueSetting.MaxExecution),
|
||||
queue.WithResumeTaskType(queue.RemoteDownloadTaskType),
|
||||
queue.WithTaskPullInterval(20*time.Second),
|
||||
)
|
||||
return d.remoteDownloadQueue
|
||||
}
|
||||
|
||||
func (d *dependency) EntityRecycleQueue(ctx context.Context) queue.Queue {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
_, reload := ctx.Value(ReloadCtx{}).(bool)
|
||||
if d.entityRecycleQueue != nil && !reload {
|
||||
return d.entityRecycleQueue
|
||||
}
|
||||
|
||||
if d.entityRecycleQueue != nil {
|
||||
d.entityRecycleQueue.Shutdown()
|
||||
}
|
||||
|
||||
settings := d.SettingProvider()
|
||||
queueSetting := settings.Queue(context.Background(), setting.QueueTypeEntityRecycle)
|
||||
|
||||
d.entityRecycleQueue = queue.New(d.Logger(), d.TaskClient(), nil, d,
|
||||
queue.WithBackoffFactor(queueSetting.BackoffFactor),
|
||||
queue.WithMaxRetry(queueSetting.MaxRetry),
|
||||
queue.WithBackoffMaxDuration(queueSetting.BackoffMaxDuration),
|
||||
queue.WithRetryDelay(queueSetting.RetryDelay),
|
||||
queue.WithWorkerCount(queueSetting.WorkerNum),
|
||||
queue.WithName("EntityRecycleQueue"),
|
||||
queue.WithMaxTaskExecution(queueSetting.MaxExecution),
|
||||
queue.WithResumeTaskType(queue.EntityRecycleRoutineTaskType, queue.ExplicitEntityRecycleTaskType, queue.UploadSentinelCheckTaskType),
|
||||
queue.WithTaskPullInterval(10*time.Second),
|
||||
)
|
||||
return d.entityRecycleQueue
|
||||
}
|
||||
|
||||
func (d *dependency) SlaveQueue(ctx context.Context) queue.Queue {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
_, reload := ctx.Value(ReloadCtx{}).(bool)
|
||||
if d.slaveQueue != nil && !reload {
|
||||
return d.slaveQueue
|
||||
}
|
||||
|
||||
if d.slaveQueue != nil {
|
||||
d.slaveQueue.Shutdown()
|
||||
}
|
||||
|
||||
settings := d.SettingProvider()
|
||||
queueSetting := settings.Queue(context.Background(), setting.QueueTypeSlave)
|
||||
|
||||
d.slaveQueue = queue.New(d.Logger(), nil, nil, d,
|
||||
queue.WithBackoffFactor(queueSetting.BackoffFactor),
|
||||
queue.WithMaxRetry(queueSetting.MaxRetry),
|
||||
queue.WithBackoffMaxDuration(queueSetting.BackoffMaxDuration),
|
||||
queue.WithRetryDelay(queueSetting.RetryDelay),
|
||||
queue.WithWorkerCount(queueSetting.WorkerNum),
|
||||
queue.WithName("SlaveQueue"),
|
||||
queue.WithMaxTaskExecution(queueSetting.MaxExecution),
|
||||
)
|
||||
return d.slaveQueue
|
||||
}
|
||||
|
||||
func (d *dependency) GeneralAuth() auth.Auth {
|
||||
if d.generalAuth != nil {
|
||||
return d.generalAuth
|
||||
}
|
||||
|
||||
var secretKey string
|
||||
if d.ConfigProvider().System().Mode == conf.MasterMode {
|
||||
secretKey = d.SettingProvider().SecretKey(context.Background())
|
||||
} else {
|
||||
secretKey = d.ConfigProvider().Slave().Secret
|
||||
if secretKey == "" {
|
||||
d.panicError(errors.New("SlaveSecret is not set, please specify it in config file"))
|
||||
}
|
||||
}
|
||||
|
||||
d.generalAuth = auth.HMACAuth{
|
||||
SecretKey: []byte(secretKey),
|
||||
}
|
||||
|
||||
return d.generalAuth
|
||||
}
|
||||
|
||||
func (d *dependency) FileClient() inventory.FileClient {
|
||||
if d.fileClient != nil {
|
||||
return d.fileClient
|
||||
}
|
||||
|
||||
return inventory.NewFileClient(d.DBClient(), d.ConfigProvider().Database().Type, d.HashIDEncoder())
|
||||
}
|
||||
|
||||
func (d *dependency) ShareClient() inventory.ShareClient {
|
||||
if d.shareClient != nil {
|
||||
return d.shareClient
|
||||
}
|
||||
|
||||
return inventory.NewShareClient(d.DBClient(), d.ConfigProvider().Database().Type, d.HashIDEncoder())
|
||||
}
|
||||
|
||||
func (d *dependency) TaskClient() inventory.TaskClient {
|
||||
if d.taskClient != nil {
|
||||
return d.taskClient
|
||||
}
|
||||
|
||||
return inventory.NewTaskClient(d.DBClient(), d.ConfigProvider().Database().Type, d.HashIDEncoder())
|
||||
}
|
||||
|
||||
func (d *dependency) DavAccountClient() inventory.DavAccountClient {
|
||||
if d.davAccountClient != nil {
|
||||
return d.davAccountClient
|
||||
}
|
||||
|
||||
return inventory.NewDavAccountClient(d.DBClient(), d.ConfigProvider().Database().Type, d.HashIDEncoder())
|
||||
}
|
||||
|
||||
func (d *dependency) DirectLinkClient() inventory.DirectLinkClient {
|
||||
if d.directLinkClient != nil {
|
||||
return d.directLinkClient
|
||||
}
|
||||
|
||||
return inventory.NewDirectLinkClient(d.DBClient(), d.ConfigProvider().Database().Type, d.HashIDEncoder())
|
||||
}
|
||||
|
||||
func (d *dependency) HashIDEncoder() hashid.Encoder {
|
||||
if d.hashidEncoder != nil {
|
||||
return d.hashidEncoder
|
||||
}
|
||||
|
||||
encoder, err := hashid.New(d.SettingProvider().HashIDSalt(context.Background()))
|
||||
if err != nil {
|
||||
d.panicError(err)
|
||||
}
|
||||
|
||||
d.hashidEncoder = encoder
|
||||
return d.hashidEncoder
|
||||
}
|
||||
|
||||
func (d *dependency) CredManager() credmanager.CredManager {
|
||||
if d.credManager != nil {
|
||||
return d.credManager
|
||||
}
|
||||
|
||||
if d.ConfigProvider().System().Mode == conf.MasterMode {
|
||||
d.credManager = credmanager.New(d.KV())
|
||||
} else {
|
||||
d.credManager = credmanager.NewSlaveManager(d.KV(), d.ConfigProvider())
|
||||
}
|
||||
return d.credManager
|
||||
}
|
||||
|
||||
func (d *dependency) TokenAuth() auth.TokenAuth {
|
||||
if d.tokenAuth != nil {
|
||||
return d.tokenAuth
|
||||
}
|
||||
|
||||
d.tokenAuth = auth.NewTokenAuth(d.HashIDEncoder(), d.SettingProvider(),
|
||||
[]byte(d.SettingProvider().SecretKey(context.Background())), d.UserClient(), d.Logger())
|
||||
return d.tokenAuth
|
||||
}
|
||||
|
||||
func (d *dependency) LockSystem() lock.LockSystem {
|
||||
if d.lockSystem != nil {
|
||||
return d.lockSystem
|
||||
}
|
||||
|
||||
d.lockSystem = lock.NewMemLS(d.HashIDEncoder(), d.Logger())
|
||||
return d.lockSystem
|
||||
}
|
||||
|
||||
func (d *dependency) StoragePolicyClient() inventory.StoragePolicyClient {
|
||||
if d.storagePolicyClient != nil {
|
||||
return d.storagePolicyClient
|
||||
}
|
||||
|
||||
return inventory.NewStoragePolicyClient(d.DBClient(), d.KV())
|
||||
}
|
||||
|
||||
func (d *dependency) ThumbPipeline() thumb.Generator {
|
||||
if d.thumbPipeline != nil {
|
||||
return d.thumbPipeline
|
||||
}
|
||||
|
||||
d.thumbPipeline = thumb.NewPipeline(d.SettingProvider(), d.Logger())
|
||||
return d.thumbPipeline
|
||||
}
|
||||
|
||||
func (d *dependency) TaskRegistry() queue.TaskRegistry {
|
||||
if d.taskRegistry != nil {
|
||||
return d.taskRegistry
|
||||
}
|
||||
|
||||
d.taskRegistry = queue.NewTaskRegistry()
|
||||
return d.taskRegistry
|
||||
}
|
||||
|
||||
func (d *dependency) Shutdown(ctx context.Context) error {
|
||||
d.mu.Lock()
|
||||
|
||||
if d.emailClient != nil {
|
||||
d.emailClient.Close()
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
|
||||
if d.mediaMetaQueue != nil {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
d.mediaMetaQueue.Shutdown()
|
||||
defer wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
if d.thumbQueue != nil {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
d.thumbQueue.Shutdown()
|
||||
defer wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
if d.ioIntenseQueue != nil {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
d.ioIntenseQueue.Shutdown()
|
||||
defer wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
if d.entityRecycleQueue != nil {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
d.entityRecycleQueue.Shutdown()
|
||||
defer wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
if d.slaveQueue != nil {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
d.slaveQueue.Shutdown()
|
||||
defer wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
if d.remoteDownloadQueue != nil {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
d.remoteDownloadQueue.Shutdown()
|
||||
defer wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
d.mu.Unlock()
|
||||
wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dependency) panicError(err error) {
|
||||
if d.logger != nil {
|
||||
d.logger.Panic("Fatal error in dependency initialization: %s", err)
|
||||
}
|
||||
|
||||
panic(err)
|
||||
}
|
||||
|
||||
func (d *dependency) ForkWithLogger(ctx context.Context, l logging.Logger) context.Context {
|
||||
dep := &dependencyCorrelated{
|
||||
l: l,
|
||||
dependency: d,
|
||||
}
|
||||
return context.WithValue(ctx, DepCtx{}, dep)
|
||||
}
|
||||
|
||||
type dependencyCorrelated struct {
|
||||
l logging.Logger
|
||||
*dependency
|
||||
}
|
||||
|
||||
func (d *dependencyCorrelated) Logger() logging.Logger {
|
||||
return d.l
|
||||
}
|
||||
Reference in New Issue
Block a user