MM-56876: Redis: first introduction (#27752)
```release-note NONE ``` --------- Co-authored-by: Jesús Espino <jespinog@gmail.com> Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
c3ed07e679
Коммит
540febd866
@@ -17,7 +17,7 @@ import (
|
||||
"github.com/mattermost/mattermost/server/v8/platform/shared/mail"
|
||||
)
|
||||
|
||||
var latestVersionCache = cache.NewLRU(cache.LRUOptions{
|
||||
var latestVersionCache = cache.NewLRU(&cache.CacheOptions{
|
||||
Size: 1,
|
||||
})
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
const LinkCacheSize = 10000
|
||||
const LinkCacheDuration = 1 * time.Hour
|
||||
|
||||
var linkCache = cache.NewLRU(cache.LRUOptions{
|
||||
var linkCache = cache.NewLRU(&cache.CacheOptions{
|
||||
Size: LinkCacheSize,
|
||||
})
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ func StoreOverride(override any) Option {
|
||||
func StoreOverrideWithCache(override store.Store) Option {
|
||||
return func(ps *PlatformService) error {
|
||||
ps.newStore = func() (store.Store, error) {
|
||||
lcl, err := localcachelayer.NewLocalCacheLayer(override, ps.metricsIFace, ps.clusterIFace, ps.cacheProvider)
|
||||
lcl, err := localcachelayer.NewLocalCacheLayer(override, ps.metricsIFace, ps.clusterIFace, ps.cacheProvider, ps.Log())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -136,21 +136,6 @@ func New(sc ServiceConfig, options ...Option) (*PlatformService, error) {
|
||||
// Assume the first user account has not been created yet. A call to the DB will later check if this is really the case.
|
||||
ps.isFirstUserAccount.Store(true)
|
||||
|
||||
// Step 1: Cache provider.
|
||||
// At the moment we only have this implementation
|
||||
// in the future the cache provider will be built based on the loaded config
|
||||
ps.cacheProvider = cache.NewProvider()
|
||||
if err2 := ps.cacheProvider.Connect(); err2 != nil {
|
||||
return nil, fmt.Errorf("unable to connect to cache provider: %w", err2)
|
||||
}
|
||||
|
||||
// Apply options, some of the options overrides the default config actually.
|
||||
for _, option := range options {
|
||||
if err := option(ps); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply option: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// the config store is not set, we need to create a new one
|
||||
if ps.configStore == nil {
|
||||
innerStore, err := config.NewFileStore("config.json", true)
|
||||
@@ -166,13 +151,46 @@ func New(sc ServiceConfig, options ...Option) (*PlatformService, error) {
|
||||
ps.configStore = configStore
|
||||
}
|
||||
|
||||
// Step 2: Start logging.
|
||||
if err := ps.initLogging(); err != nil {
|
||||
return nil, fmt.Errorf("failed to initialize logging: %w", err)
|
||||
// Step 1: Cache provider.
|
||||
cacheConfig := ps.configStore.Get().CacheSettings
|
||||
var err error
|
||||
if *cacheConfig.CacheType == model.CacheTypeLRU {
|
||||
ps.cacheProvider = cache.NewProvider()
|
||||
} else if *cacheConfig.CacheType == model.CacheTypeRedis {
|
||||
ps.cacheProvider, err = cache.NewRedisProvider(
|
||||
&cache.RedisOptions{
|
||||
RedisAddr: *cacheConfig.RedisAddress,
|
||||
RedisPassword: *cacheConfig.RedisPassword,
|
||||
RedisDB: *cacheConfig.RedisDB,
|
||||
},
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create cache provider: %w", err)
|
||||
}
|
||||
|
||||
// The value of res is used later, after the logger is initialized.
|
||||
// There's a certain order of steps we need to follow in the server startup phase.
|
||||
res, err := ps.cacheProvider.Connect()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to connect to cache provider: %w", err)
|
||||
}
|
||||
|
||||
// Apply options, some of the options overrides the default config actually.
|
||||
for _, option := range options {
|
||||
if err2 := option(ps); err2 != nil {
|
||||
return nil, fmt.Errorf("failed to apply option: %w", err2)
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Start logging.
|
||||
if err2 := ps.initLogging(); err2 != nil {
|
||||
return nil, fmt.Errorf("failed to initialize logging: %w", err2)
|
||||
}
|
||||
ps.Log().Info("Successfully connected to cache backend", mlog.String("backend", *cacheConfig.CacheType), mlog.String("result", res))
|
||||
|
||||
// This is called after initLogging() to avoid a race condition.
|
||||
mlog.Info("Server is initializing...", mlog.String("go_version", runtime.Version()))
|
||||
ps.Log().Info("Server is initializing...", mlog.String("go_version", runtime.Version()))
|
||||
|
||||
// Step 3: Search Engine
|
||||
searchEngine := searchengine.NewBroker(ps.Config())
|
||||
@@ -192,6 +210,8 @@ func New(sc ServiceConfig, options ...Option) (*PlatformService, error) {
|
||||
ps.metricsIFace = metricsInterfaceFn(ps, *ps.configStore.Get().SqlSettings.DriverName, *ps.configStore.Get().SqlSettings.DataSource)
|
||||
}
|
||||
|
||||
ps.cacheProvider.SetMetrics(ps.metricsIFace)
|
||||
|
||||
// Step 6: Store.
|
||||
// Depends on Step 0 (config), 1 (cacheProvider), 3 (search engine), 5 (metrics) and cluster.
|
||||
if ps.newStore == nil {
|
||||
@@ -206,7 +226,6 @@ func New(sc ServiceConfig, options ...Option) (*PlatformService, error) {
|
||||
// Timer layer
|
||||
// |
|
||||
// Cache layer
|
||||
var err error
|
||||
ps.sqlStore, err = sqlstore.New(ps.Config().SqlSettings, ps.Log(), ps.metricsIFace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -227,6 +246,7 @@ func New(sc ServiceConfig, options ...Option) (*PlatformService, error) {
|
||||
ps.metricsIFace,
|
||||
ps.clusterIFace,
|
||||
ps.cacheProvider,
|
||||
ps.Log(),
|
||||
)
|
||||
if err2 != nil {
|
||||
return nil, fmt.Errorf("cannot create local cache layer: %w", err2)
|
||||
@@ -267,14 +287,13 @@ func New(sc ServiceConfig, options ...Option) (*PlatformService, error) {
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
ps.Store, err = ps.newStore()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create store: %w", err)
|
||||
}
|
||||
|
||||
// Needed before loading license
|
||||
ps.statusCache, err = ps.cacheProvider.NewCache(&cache.CacheOptions{
|
||||
ps.statusCache, err = cache.NewProvider().NewCache(&cache.CacheOptions{
|
||||
Name: "Status",
|
||||
Size: model.StatusCacheSize,
|
||||
Striped: true,
|
||||
@@ -284,7 +303,8 @@ func New(sc ServiceConfig, options ...Option) (*PlatformService, error) {
|
||||
return nil, fmt.Errorf("unable to create status cache: %w", err)
|
||||
}
|
||||
|
||||
ps.sessionCache, err = ps.cacheProvider.NewCache(&cache.CacheOptions{
|
||||
ps.sessionCache, err = cache.NewProvider().NewCache(&cache.CacheOptions{
|
||||
Name: "Session",
|
||||
Size: model.SessionCacheSize,
|
||||
Striped: true,
|
||||
StripedBuckets: maxInt(runtime.NumCPU()-1, 1),
|
||||
|
||||
@@ -118,7 +118,7 @@ func (a *App) deduplicateCreatePost(rctx request.CTX, post *model.Post) (foundPo
|
||||
}
|
||||
|
||||
if nErr != nil {
|
||||
return nil, model.NewAppError("errorGetPostId", "api.post.error_get_post_id.pending", nil, "", http.StatusInternalServerError)
|
||||
return nil, model.NewAppError("errorGetPostId", "api.post.error_get_post_id.pending", nil, "", http.StatusInternalServerError).Wrap(nErr)
|
||||
}
|
||||
|
||||
// If another thread saved the cache record, but hasn't yet updated it with the actual post
|
||||
|
||||
@@ -305,11 +305,13 @@ func NewServer(options ...Option) (*Server, error) {
|
||||
model.AppErrorInit(i18n.T)
|
||||
|
||||
if s.seenPendingPostIdsCache, err = s.platform.CacheProvider().NewCache(&cache.CacheOptions{
|
||||
Name: "seen_pending_post_ids",
|
||||
Size: PendingPostIDsCacheSize,
|
||||
}); err != nil {
|
||||
return nil, errors.Wrap(err, "Unable to create pending post ids cache")
|
||||
}
|
||||
if s.openGraphDataCache, err = s.platform.CacheProvider().NewCache(&cache.CacheOptions{
|
||||
Name: "opengraph_data",
|
||||
Size: openGraphMetadataCacheSize,
|
||||
}); err != nil {
|
||||
return nil, errors.Wrap(err, "Unable to create opengraphdata cache")
|
||||
|
||||
Ссылка в новой задаче
Block a user