Boards data retention (#19262)
* add Boards to DataRetention, add hook for data retention * remove replaces * update hook to remove parameter * add boards data retention to telemetry * fix unit test * update test, update hooks * update RunDataRetention server version * put behind a feature flag Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
294bd44971
Коммит
956e21cfa2
@@ -1215,3 +1215,47 @@ func TestHookReactionHasBeenRemoved(t *testing.T) {
|
|||||||
|
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHookRunDataRetention(t *testing.T) {
|
||||||
|
th := Setup(t).InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
|
||||||
|
tearDown, pluginIDs, _ := SetAppEnvironmentWithPlugins(t,
|
||||||
|
[]string{
|
||||||
|
`
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mattermost/mattermost-server/v6/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MyPlugin struct {
|
||||||
|
plugin.MattermostPlugin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MyPlugin) RunDataRetention(nowMillis, batchSize int64) (int64, error){
|
||||||
|
return 100, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
plugin.ClientMain(&MyPlugin{})
|
||||||
|
}
|
||||||
|
`}, th.App, th.NewPluginAPI)
|
||||||
|
defer tearDown()
|
||||||
|
|
||||||
|
require.Len(t, pluginIDs, 1)
|
||||||
|
pluginID := pluginIDs[0]
|
||||||
|
|
||||||
|
require.True(t, th.App.GetPluginsEnvironment().IsActive(pluginID))
|
||||||
|
|
||||||
|
hookCalled := false
|
||||||
|
th.App.GetPluginsEnvironment().RunMultiPluginHook(func(hooks plugin.Hooks) bool {
|
||||||
|
n, _ := hooks.RunDataRetention(0, 0)
|
||||||
|
// Ensure return it correct
|
||||||
|
assert.Equal(t, int64(100), n)
|
||||||
|
hookCalled = true
|
||||||
|
return hookCalled
|
||||||
|
}, plugin.RunDataRetentionID)
|
||||||
|
|
||||||
|
require.True(t, hookCalled)
|
||||||
|
}
|
||||||
|
|||||||
@@ -126,6 +126,8 @@ func GenerateClientConfig(c *model.Config, telemetryID string, license *model.Li
|
|||||||
props["DataRetentionMessageRetentionDays"] = "0"
|
props["DataRetentionMessageRetentionDays"] = "0"
|
||||||
props["DataRetentionEnableFileDeletion"] = "false"
|
props["DataRetentionEnableFileDeletion"] = "false"
|
||||||
props["DataRetentionFileRetentionDays"] = "0"
|
props["DataRetentionFileRetentionDays"] = "0"
|
||||||
|
props["DataRetentionEnableBoardsDeletion"] = "false"
|
||||||
|
props["DataRetentionBoardsRetentionDays"] = "0"
|
||||||
props["CWSURL"] = ""
|
props["CWSURL"] = ""
|
||||||
|
|
||||||
props["CustomUrlSchemes"] = strings.Join(c.DisplaySettings.CustomURLSchemes, ",")
|
props["CustomUrlSchemes"] = strings.Join(c.DisplaySettings.CustomURLSchemes, ",")
|
||||||
@@ -190,6 +192,8 @@ func GenerateClientConfig(c *model.Config, telemetryID string, license *model.Li
|
|||||||
props["DataRetentionMessageRetentionDays"] = strconv.FormatInt(int64(*c.DataRetentionSettings.MessageRetentionDays), 10)
|
props["DataRetentionMessageRetentionDays"] = strconv.FormatInt(int64(*c.DataRetentionSettings.MessageRetentionDays), 10)
|
||||||
props["DataRetentionEnableFileDeletion"] = strconv.FormatBool(*c.DataRetentionSettings.EnableFileDeletion)
|
props["DataRetentionEnableFileDeletion"] = strconv.FormatBool(*c.DataRetentionSettings.EnableFileDeletion)
|
||||||
props["DataRetentionFileRetentionDays"] = strconv.FormatInt(int64(*c.DataRetentionSettings.FileRetentionDays), 10)
|
props["DataRetentionFileRetentionDays"] = strconv.FormatInt(int64(*c.DataRetentionSettings.FileRetentionDays), 10)
|
||||||
|
props["DataRetentionEnableBoardsDeletion"] = strconv.FormatBool(*c.DataRetentionSettings.EnableBoardsDeletion)
|
||||||
|
props["DataRetentionBoardsRetentionDays"] = strconv.FormatInt(int64(*c.DataRetentionSettings.BoardsRetentionDays), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *license.Features.Cloud {
|
if *license.Features.Cloud {
|
||||||
|
|||||||
@@ -221,9 +221,9 @@ func (workers *Workers) handleConfigChange(oldConfig *model.Config, newConfig *m
|
|||||||
mlog.Debug("Workers received config change.")
|
mlog.Debug("Workers received config change.")
|
||||||
|
|
||||||
if workers.DataRetention != nil {
|
if workers.DataRetention != nil {
|
||||||
if (!*oldConfig.DataRetentionSettings.EnableMessageDeletion && !*oldConfig.DataRetentionSettings.EnableFileDeletion) && (*newConfig.DataRetentionSettings.EnableMessageDeletion || *newConfig.DataRetentionSettings.EnableFileDeletion) {
|
if (!*oldConfig.DataRetentionSettings.EnableMessageDeletion && !*oldConfig.DataRetentionSettings.EnableFileDeletion && !*oldConfig.DataRetentionSettings.EnableBoardsDeletion) && (*newConfig.DataRetentionSettings.EnableMessageDeletion || *newConfig.DataRetentionSettings.EnableFileDeletion || *newConfig.DataRetentionSettings.EnableBoardsDeletion) {
|
||||||
go workers.DataRetention.Run()
|
go workers.DataRetention.Run()
|
||||||
} else if (*oldConfig.DataRetentionSettings.EnableMessageDeletion || *oldConfig.DataRetentionSettings.EnableFileDeletion) && (!*newConfig.DataRetentionSettings.EnableMessageDeletion && !*newConfig.DataRetentionSettings.EnableFileDeletion) {
|
} else if (*oldConfig.DataRetentionSettings.EnableMessageDeletion || *oldConfig.DataRetentionSettings.EnableFileDeletion || *oldConfig.DataRetentionSettings.EnableBoardsDeletion) && (!*newConfig.DataRetentionSettings.EnableMessageDeletion && !*newConfig.DataRetentionSettings.EnableFileDeletion && !*newConfig.DataRetentionSettings.EnableBoardsDeletion) {
|
||||||
workers.DataRetention.Stop()
|
workers.DataRetention.Stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ const (
|
|||||||
|
|
||||||
DataRetentionSettingsDefaultMessageRetentionDays = 365
|
DataRetentionSettingsDefaultMessageRetentionDays = 365
|
||||||
DataRetentionSettingsDefaultFileRetentionDays = 365
|
DataRetentionSettingsDefaultFileRetentionDays = 365
|
||||||
|
DataRetentionSettingsDefaultBoardsRetentionDays = 365
|
||||||
DataRetentionSettingsDefaultDeletionJobStartTime = "02:00"
|
DataRetentionSettingsDefaultDeletionJobStartTime = "02:00"
|
||||||
DataRetentionSettingsDefaultBatchSize = 3000
|
DataRetentionSettingsDefaultBatchSize = 3000
|
||||||
|
|
||||||
@@ -2586,8 +2587,10 @@ func (bs *BleveSettings) SetDefaults() {
|
|||||||
type DataRetentionSettings struct {
|
type DataRetentionSettings struct {
|
||||||
EnableMessageDeletion *bool `access:"compliance_data_retention_policy"`
|
EnableMessageDeletion *bool `access:"compliance_data_retention_policy"`
|
||||||
EnableFileDeletion *bool `access:"compliance_data_retention_policy"`
|
EnableFileDeletion *bool `access:"compliance_data_retention_policy"`
|
||||||
|
EnableBoardsDeletion *bool `access:"compliance_data_retention_policy"`
|
||||||
MessageRetentionDays *int `access:"compliance_data_retention_policy"`
|
MessageRetentionDays *int `access:"compliance_data_retention_policy"`
|
||||||
FileRetentionDays *int `access:"compliance_data_retention_policy"`
|
FileRetentionDays *int `access:"compliance_data_retention_policy"`
|
||||||
|
BoardsRetentionDays *int `access:"compliance_data_retention_policy"`
|
||||||
DeletionJobStartTime *string `access:"compliance_data_retention_policy"`
|
DeletionJobStartTime *string `access:"compliance_data_retention_policy"`
|
||||||
BatchSize *int `access:"compliance_data_retention_policy"`
|
BatchSize *int `access:"compliance_data_retention_policy"`
|
||||||
}
|
}
|
||||||
@@ -2601,6 +2604,10 @@ func (s *DataRetentionSettings) SetDefaults() {
|
|||||||
s.EnableFileDeletion = NewBool(false)
|
s.EnableFileDeletion = NewBool(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.EnableBoardsDeletion == nil {
|
||||||
|
s.EnableBoardsDeletion = NewBool(false)
|
||||||
|
}
|
||||||
|
|
||||||
if s.MessageRetentionDays == nil {
|
if s.MessageRetentionDays == nil {
|
||||||
s.MessageRetentionDays = NewInt(DataRetentionSettingsDefaultMessageRetentionDays)
|
s.MessageRetentionDays = NewInt(DataRetentionSettingsDefaultMessageRetentionDays)
|
||||||
}
|
}
|
||||||
@@ -2609,6 +2616,10 @@ func (s *DataRetentionSettings) SetDefaults() {
|
|||||||
s.FileRetentionDays = NewInt(DataRetentionSettingsDefaultFileRetentionDays)
|
s.FileRetentionDays = NewInt(DataRetentionSettingsDefaultFileRetentionDays)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.BoardsRetentionDays == nil {
|
||||||
|
s.BoardsRetentionDays = NewInt(DataRetentionSettingsDefaultBoardsRetentionDays)
|
||||||
|
}
|
||||||
|
|
||||||
if s.DeletionJobStartTime == nil {
|
if s.DeletionJobStartTime == nil {
|
||||||
s.DeletionJobStartTime = NewString(DataRetentionSettingsDefaultDeletionJobStartTime)
|
s.DeletionJobStartTime = NewString(DataRetentionSettingsDefaultDeletionJobStartTime)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ package model
|
|||||||
type GlobalRetentionPolicy struct {
|
type GlobalRetentionPolicy struct {
|
||||||
MessageDeletionEnabled bool `json:"message_deletion_enabled"`
|
MessageDeletionEnabled bool `json:"message_deletion_enabled"`
|
||||||
FileDeletionEnabled bool `json:"file_deletion_enabled"`
|
FileDeletionEnabled bool `json:"file_deletion_enabled"`
|
||||||
|
BoardsDeletionEnabled bool `json:"boards_deletion_enabled"`
|
||||||
MessageRetentionCutoff int64 `json:"message_retention_cutoff"`
|
MessageRetentionCutoff int64 `json:"message_retention_cutoff"`
|
||||||
FileRetentionCutoff int64 `json:"file_retention_cutoff"`
|
FileRetentionCutoff int64 `json:"file_retention_cutoff"`
|
||||||
|
BoardsRetentionCutoff int64 `json:"boards_retention_cutoff"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RetentionPolicy struct {
|
type RetentionPolicy struct {
|
||||||
|
|||||||
@@ -71,6 +71,9 @@ type FeatureFlags struct {
|
|||||||
// Enable inline post editing
|
// Enable inline post editing
|
||||||
InlinePostEditing bool
|
InlinePostEditing bool
|
||||||
|
|
||||||
|
// Enable DataRetention for Boards
|
||||||
|
BoardsDataRetention bool
|
||||||
|
|
||||||
NormalizeLdapDNs bool
|
NormalizeLdapDNs bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +99,7 @@ func (f *FeatureFlags) SetDefaults() {
|
|||||||
f.ResendInviteEmailInterval = ""
|
f.ResendInviteEmailInterval = ""
|
||||||
f.InviteToTeam = "none"
|
f.InviteToTeam = "none"
|
||||||
f.InlinePostEditing = false
|
f.InlinePostEditing = false
|
||||||
|
f.BoardsDataRetention = false
|
||||||
f.NormalizeLdapDNs = false
|
f.NormalizeLdapDNs = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -669,6 +669,43 @@ func (s *hooksRPCServer) WebSocketMessageHasBeenPosted(args *Z_WebSocketMessageH
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
hookNameToId["RunDataRetention"] = RunDataRetentionID
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_RunDataRetentionArgs struct {
|
||||||
|
A int64
|
||||||
|
B int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Z_RunDataRetentionReturns struct {
|
||||||
|
A int64
|
||||||
|
B error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *hooksRPCClient) RunDataRetention(nowTime, batchSize int64) (int64, error) {
|
||||||
|
_args := &Z_RunDataRetentionArgs{nowTime, batchSize}
|
||||||
|
_returns := &Z_RunDataRetentionReturns{}
|
||||||
|
if g.implemented[RunDataRetentionID] {
|
||||||
|
if err := g.client.Call("Plugin.RunDataRetention", _args, _returns); err != nil {
|
||||||
|
g.log.Error("RPC call RunDataRetention to plugin failed.", mlog.Err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _returns.A, _returns.B
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hooksRPCServer) RunDataRetention(args *Z_RunDataRetentionArgs, returns *Z_RunDataRetentionReturns) error {
|
||||||
|
if hook, ok := s.impl.(interface {
|
||||||
|
RunDataRetention(nowTime, batchSize int64) (int64, error)
|
||||||
|
}); ok {
|
||||||
|
returns.A, returns.B = hook.RunDataRetention(args.A, args.B)
|
||||||
|
returns.B = encodableError(returns.B)
|
||||||
|
} else {
|
||||||
|
return encodableError(fmt.Errorf("Hook RunDataRetention called but not implemented."))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Z_RegisterCommandArgs struct {
|
type Z_RegisterCommandArgs struct {
|
||||||
A *model.Command
|
A *model.Command
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ const (
|
|||||||
OnWebSocketConnectID = 21
|
OnWebSocketConnectID = 21
|
||||||
OnWebSocketDisconnectID = 22
|
OnWebSocketDisconnectID = 22
|
||||||
WebSocketMessageHasBeenPostedID = 23
|
WebSocketMessageHasBeenPostedID = 23
|
||||||
|
RunDataRetentionID = 24
|
||||||
TotalHooksID = iota
|
TotalHooksID = iota
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -243,4 +244,9 @@ type Hooks interface {
|
|||||||
//
|
//
|
||||||
// Minimum server version: 6.0
|
// Minimum server version: 6.0
|
||||||
WebSocketMessageHasBeenPosted(webConnID, userID string, req *model.WebSocketRequest)
|
WebSocketMessageHasBeenPosted(webConnID, userID string, req *model.WebSocketRequest)
|
||||||
|
|
||||||
|
// RunDataRetention is invoked during a DataRetentionJob
|
||||||
|
//
|
||||||
|
// Minimum server version: 6.4
|
||||||
|
RunDataRetention(nowTime, batchSize int64) (int64, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,3 +186,10 @@ func (hooks *hooksTimerLayer) WebSocketMessageHasBeenPosted(webConnID, userID st
|
|||||||
hooks.hooksImpl.WebSocketMessageHasBeenPosted(webConnID, userID, req)
|
hooks.hooksImpl.WebSocketMessageHasBeenPosted(webConnID, userID, req)
|
||||||
hooks.recordTime(startTime, "WebSocketMessageHasBeenPosted", true)
|
hooks.recordTime(startTime, "WebSocketMessageHasBeenPosted", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hooks *hooksTimerLayer) RunDataRetention(nowTime, batchSize int64) (int64, error) {
|
||||||
|
startTime := timePkg.Now()
|
||||||
|
_returnsA, _returnsB := hooks.hooksImpl.RunDataRetention(nowTime, batchSize)
|
||||||
|
hooks.recordTime(startTime, "RunDataRetention", _returnsB == nil)
|
||||||
|
return _returnsA, _returnsB
|
||||||
|
}
|
||||||
|
|||||||
@@ -219,6 +219,27 @@ func (_m *Hooks) ReactionHasBeenRemoved(c *plugin.Context, reaction *model.React
|
|||||||
_m.Called(c, reaction)
|
_m.Called(c, reaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RunDataRetention provides a mock function with given fields: nowTime, batchSize
|
||||||
|
func (_m *Hooks) RunDataRetention(nowTime int64, batchSize int64) (int64, error) {
|
||||||
|
ret := _m.Called(nowTime, batchSize)
|
||||||
|
|
||||||
|
var r0 int64
|
||||||
|
if rf, ok := ret.Get(0).(func(int64, int64) int64); ok {
|
||||||
|
r0 = rf(nowTime, batchSize)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int64)
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(int64, int64) error); ok {
|
||||||
|
r1 = rf(nowTime, batchSize)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// ServeHTTP provides a mock function with given fields: c, w, r
|
// ServeHTTP provides a mock function with given fields: c, w, r
|
||||||
func (_m *Hooks) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
|
func (_m *Hooks) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
|
||||||
_m.Called(c, w, r)
|
_m.Called(c, w, r)
|
||||||
|
|||||||
@@ -758,8 +758,10 @@ func (ts *TelemetryService) trackConfig() {
|
|||||||
ts.SendTelemetry(TrackConfigDataRetention, map[string]interface{}{
|
ts.SendTelemetry(TrackConfigDataRetention, map[string]interface{}{
|
||||||
"enable_message_deletion": *cfg.DataRetentionSettings.EnableMessageDeletion,
|
"enable_message_deletion": *cfg.DataRetentionSettings.EnableMessageDeletion,
|
||||||
"enable_file_deletion": *cfg.DataRetentionSettings.EnableFileDeletion,
|
"enable_file_deletion": *cfg.DataRetentionSettings.EnableFileDeletion,
|
||||||
|
"enable_boards_deletion": *cfg.DataRetentionSettings.EnableBoardsDeletion,
|
||||||
"message_retention_days": *cfg.DataRetentionSettings.MessageRetentionDays,
|
"message_retention_days": *cfg.DataRetentionSettings.MessageRetentionDays,
|
||||||
"file_retention_days": *cfg.DataRetentionSettings.FileRetentionDays,
|
"file_retention_days": *cfg.DataRetentionSettings.FileRetentionDays,
|
||||||
|
"boards_retention_days": *cfg.DataRetentionSettings.BoardsRetentionDays,
|
||||||
"deletion_job_start_time": *cfg.DataRetentionSettings.DeletionJobStartTime,
|
"deletion_job_start_time": *cfg.DataRetentionSettings.DeletionJobStartTime,
|
||||||
"batch_size": *cfg.DataRetentionSettings.BatchSize,
|
"batch_size": *cfg.DataRetentionSettings.BatchSize,
|
||||||
"cleanup_jobs_threshold_days": *cfg.JobSettings.CleanupJobsThresholdDays,
|
"cleanup_jobs_threshold_days": *cfg.JobSettings.CleanupJobsThresholdDays,
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user