Implement event pruning

This commit is contained in:
cuigh 2022-01-04 16:44:03 +08:00
parent e70d907c06
commit d0eb101aee
9 changed files with 62 additions and 8 deletions

View File

@ -2,7 +2,6 @@ package api
import ( import (
"github.com/cuigh/auxo/data" "github.com/cuigh/auxo/data"
"github.com/cuigh/auxo/errors"
"github.com/cuigh/auxo/net/web" "github.com/cuigh/auxo/net/web"
"github.com/cuigh/swirl/biz" "github.com/cuigh/swirl/biz"
"github.com/cuigh/swirl/dao" "github.com/cuigh/swirl/dao"
@ -47,15 +46,13 @@ func eventSearch(b biz.EventBiz) web.HandlerFunc {
func eventPrune(b biz.EventBiz) web.HandlerFunc { func eventPrune(b biz.EventBiz) web.HandlerFunc {
type Args struct { type Args struct {
Date string `json:"date"` Days int32 `json:"days"`
} }
return func(ctx web.Context) (err error) { return func(ctx web.Context) (err error) {
var args = &Args{} var args = &Args{}
if err = ctx.Bind(args); err == nil { if err = ctx.Bind(args); err == nil {
// TODO err = b.Prune(args.Days)
//err = b.Prune(args.Date)
err = errors.NotImplemented
} }
return ajax(ctx, err) return ajax(ctx, err)
} }

View File

@ -2,8 +2,10 @@ package biz
import ( import (
"context" "context"
"time"
"github.com/cuigh/auxo/data" "github.com/cuigh/auxo/data"
"github.com/cuigh/auxo/ext/times"
"github.com/cuigh/auxo/log" "github.com/cuigh/auxo/log"
"github.com/cuigh/auxo/net/web" "github.com/cuigh/auxo/net/web"
"github.com/cuigh/swirl/dao" "github.com/cuigh/swirl/dao"
@ -47,6 +49,7 @@ const (
type EventBiz interface { type EventBiz interface {
Search(args *dao.EventSearchArgs) (events []*dao.Event, total int, err error) Search(args *dao.EventSearchArgs) (events []*dao.Event, total int, err error)
Prune(days int32) (err error)
CreateRegistry(action EventAction, id, name string, user web.User) CreateRegistry(action EventAction, id, name string, user web.User)
CreateNode(action EventAction, id, name string, user web.User) CreateNode(action EventAction, id, name string, user web.User)
CreateNetwork(action EventAction, id, name string, user web.User) CreateNetwork(action EventAction, id, name string, user web.User)
@ -75,6 +78,10 @@ func (b *eventBiz) Search(args *dao.EventSearchArgs) (events []*dao.Event, total
return b.d.EventSearch(context.TODO(), args) return b.d.EventSearch(context.TODO(), args)
} }
func (b *eventBiz) Prune(days int32) (err error) {
return b.d.EventPrune(context.TODO(), time.Now().Add(-times.Days(days)))
}
func (b *eventBiz) create(et EventType, ea EventAction, args data.Map, user web.User) { func (b *eventBiz) create(et EventType, ea EventAction, args data.Map, user web.User) {
event := &dao.Event{ event := &dao.Event{
ID: primitive.NewObjectID(), ID: primitive.NewObjectID(),

View File

@ -5,6 +5,7 @@ import (
"sort" "sort"
"time" "time"
"github.com/boltdb/bolt"
"github.com/cuigh/auxo/util/cast" "github.com/cuigh/auxo/util/cast"
"github.com/cuigh/swirl/dao" "github.com/cuigh/swirl/dao"
"github.com/cuigh/swirl/misc" "github.com/cuigh/swirl/misc"
@ -47,3 +48,16 @@ func (d *Dao) EventSearch(ctx context.Context, args *dao.EventSearchArgs) (event
func (d *Dao) EventCreate(ctx context.Context, event *dao.Event) (err error) { func (d *Dao) EventCreate(ctx context.Context, event *dao.Event) (err error) {
return d.replace(Event, event.ID.Hex(), event) return d.replace(Event, event.ID.Hex(), event)
} }
func (d *Dao) EventPrune(ctx context.Context, end time.Time) (err error) {
return d.db.Update(func(tx *bolt.Tx) (err error) {
b := tx.Bucket([]byte(Event))
return b.ForEach(func(k, v []byte) error {
event := &dao.Event{}
if err = decode(v, event); err == nil && time.Time(event.Time).Before(end) {
err = b.Delete(k)
}
return err
})
})
}

View File

@ -61,6 +61,7 @@ type Interface interface {
EventSearch(ctx context.Context, args *EventSearchArgs) (events []*Event, count int, err error) EventSearch(ctx context.Context, args *EventSearchArgs) (events []*Event, count int, err error)
EventCreate(ctx context.Context, event *Event) error EventCreate(ctx context.Context, event *Event) error
EventPrune(ctx context.Context, end time.Time) (err error)
SettingGet(ctx context.Context, id string) (*Setting, error) SettingGet(ctx context.Context, id string) (*Setting, error)
SettingGetAll(ctx context.Context) (settings []*Setting, err error) SettingGetAll(ctx context.Context) (settings []*Setting, err error)

View File

@ -2,6 +2,7 @@ package mongo
import ( import (
"context" "context"
"time"
"github.com/cuigh/swirl/dao" "github.com/cuigh/swirl/dao"
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
@ -26,3 +27,9 @@ func (d *Dao) EventSearch(ctx context.Context, args *dao.EventSearchArgs) (event
func (d *Dao) EventCreate(ctx context.Context, event *dao.Event) (err error) { func (d *Dao) EventCreate(ctx context.Context, event *dao.Event) (err error) {
return d.create(ctx, Event, event) return d.create(ctx, Event, event)
} }
func (d *Dao) EventPrune(ctx context.Context, end time.Time) (err error) {
filter := bson.M{"time": bson.M{"$lt": end}}
_, err = d.db.Collection(Event).DeleteMany(ctx, filter)
return
}

View File

@ -28,6 +28,10 @@ export class EventApi {
search(args: SearchArgs) { search(args: SearchArgs) {
return ajax.get<SearchResult>('/event/search', args) return ajax.get<SearchResult>('/event/search', args)
} }
prune(days: number) {
return ajax.post<Result<Object>>('/event/prune', { days })
}
} }
export default new EventApi export default new EventApi

View File

@ -247,6 +247,10 @@ export default {
"title": "Prune volume", "title": "Prune volume",
"body": "Are you sure you want to clean up unused data volumes?", "body": "Are you sure you want to clean up unused data volumes?",
}, },
"prune_event": {
"title": "Prune event",
"label": "Retention days",
},
}, },
"objects": { "objects": {
"registry": "Registry | Registries", "registry": "Registry | Registries",

View File

@ -247,6 +247,10 @@ export default {
"title": "清理数据卷", "title": "清理数据卷",
"body": "是否确实要清理未使用的数据卷?", "body": "是否确实要清理未使用的数据卷?",
}, },
"prune_event": {
"title": "清理事件",
"label": "保留天数",
},
}, },
"objects": { "objects": {
"registry": "镜像仓库", "registry": "镜像仓库",

View File

@ -45,7 +45,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive } from "vue"; import { h, reactive, ref } from "vue";
import { import {
NSpace, NSpace,
NButton, NButton,
@ -53,6 +53,8 @@ import {
NSelect, NSelect,
NInput, NInput,
NIcon, NIcon,
NFormItem,
NInputNumber,
} from "naive-ui"; } from "naive-ui";
import { CloseOutline as CloseIcon } from "@vicons/ionicons5"; import { CloseOutline as CloseIcon } from "@vicons/ionicons5";
import XPageHeader from "@/components/PageHeader.vue"; import XPageHeader from "@/components/PageHeader.vue";
@ -61,7 +63,6 @@ import type { Event } from "@/api/event";
import { useDataTable } from "@/utils/data-table"; import { useDataTable } from "@/utils/data-table";
import { renderLink, renderTag, renderTime } from "@/utils/render"; import { renderLink, renderTag, renderTime } from "@/utils/render";
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import type { RouteLocationRaw } from "vue-router";
const { t } = useI18n() const { t } = useI18n()
const filter = reactive({ const filter = reactive({
@ -225,6 +226,21 @@ function renderObject(e: Event) {
} }
function prune() { function prune() {
window.message.info("TODO...") const days = ref(7) as any
window.dialog.warning({
title: t('dialogs.prune_event.title'),
content: () => h(
NFormItem,
{ label: t('dialogs.prune_event.label'), labelPlacement: 'top', showFeedback: false },
{ default: () => h(NInputNumber, { min: 0, defaultValue: days, style: 'width: 100%' }) }
),
positiveText: t('buttons.confirm'),
negativeText: t('buttons.cancel'),
onPositiveClick: async () => {
eventApi.prune(days.value);
window.message.success(t('texts.action_success'))
fetchData()
}
})
} }
</script> </script>