Emit TTL purge events
This commit is contained in:
parent
9610dd1ff2
commit
e5a0f66e08
3 changed files with 111 additions and 8 deletions
36
scope.go
36
scope.go
|
|
@ -386,10 +386,26 @@ func (scopedStore *ScopedStore) PurgeExpired() (int64, error) {
|
|||
return 0, err
|
||||
}
|
||||
|
||||
removedRows, err := purgeExpiredMatchingGroupPrefix(scopedStore.store.sqliteDatabase, scopedStore.namespacePrefix())
|
||||
cutoffUnixMilli := time.Now().UnixMilli()
|
||||
expiredEntries, err := listExpiredEntriesMatchingGroupPrefix(scopedStore.store.sqliteDatabase, scopedStore.namespacePrefix(), cutoffUnixMilli)
|
||||
if err != nil {
|
||||
return 0, core.E("store.ScopedStore.PurgeExpired", "list expired rows", err)
|
||||
}
|
||||
|
||||
removedRows, err := purgeExpiredMatchingGroupPrefix(scopedStore.store.sqliteDatabase, scopedStore.namespacePrefix(), cutoffUnixMilli)
|
||||
if err != nil {
|
||||
return 0, core.E("store.ScopedStore.PurgeExpired", "delete expired rows", err)
|
||||
}
|
||||
if removedRows > 0 {
|
||||
for _, expiredEntry := range expiredEntries {
|
||||
scopedStore.store.notify(Event{
|
||||
Type: EventDelete,
|
||||
Group: expiredEntry.group,
|
||||
Key: expiredEntry.key,
|
||||
Timestamp: time.Now(),
|
||||
})
|
||||
}
|
||||
}
|
||||
return removedRows, nil
|
||||
}
|
||||
|
||||
|
|
@ -792,10 +808,26 @@ func (scopedStoreTransaction *ScopedStoreTransaction) PurgeExpired() (int64, err
|
|||
return 0, err
|
||||
}
|
||||
|
||||
removedRows, err := purgeExpiredMatchingGroupPrefix(scopedStoreTransaction.storeTransaction.sqliteTransaction, scopedStoreTransaction.scopedStore.namespacePrefix())
|
||||
cutoffUnixMilli := time.Now().UnixMilli()
|
||||
expiredEntries, err := listExpiredEntriesMatchingGroupPrefix(scopedStoreTransaction.storeTransaction.sqliteTransaction, scopedStoreTransaction.scopedStore.namespacePrefix(), cutoffUnixMilli)
|
||||
if err != nil {
|
||||
return 0, core.E("store.ScopedStoreTransaction.PurgeExpired", "list expired rows", err)
|
||||
}
|
||||
|
||||
removedRows, err := purgeExpiredMatchingGroupPrefix(scopedStoreTransaction.storeTransaction.sqliteTransaction, scopedStoreTransaction.scopedStore.namespacePrefix(), cutoffUnixMilli)
|
||||
if err != nil {
|
||||
return 0, core.E("store.ScopedStoreTransaction.PurgeExpired", "delete expired rows", err)
|
||||
}
|
||||
if removedRows > 0 {
|
||||
for _, expiredEntry := range expiredEntries {
|
||||
scopedStoreTransaction.storeTransaction.recordEvent(Event{
|
||||
Type: EventDelete,
|
||||
Group: expiredEntry.group,
|
||||
Key: expiredEntry.key,
|
||||
Timestamp: time.Now(),
|
||||
})
|
||||
}
|
||||
}
|
||||
return removedRows, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
65
store.go
65
store.go
|
|
@ -959,10 +959,26 @@ func (storeInstance *Store) PurgeExpired() (int64, error) {
|
|||
return 0, err
|
||||
}
|
||||
|
||||
removedRows, err := purgeExpiredMatchingGroupPrefix(storeInstance.sqliteDatabase, "")
|
||||
cutoffUnixMilli := time.Now().UnixMilli()
|
||||
expiredEntries, err := listExpiredEntriesMatchingGroupPrefix(storeInstance.sqliteDatabase, "", cutoffUnixMilli)
|
||||
if err != nil {
|
||||
return 0, core.E("store.PurgeExpired", "list expired rows", err)
|
||||
}
|
||||
|
||||
removedRows, err := purgeExpiredMatchingGroupPrefix(storeInstance.sqliteDatabase, "", cutoffUnixMilli)
|
||||
if err != nil {
|
||||
return 0, core.E("store.PurgeExpired", "delete expired rows", err)
|
||||
}
|
||||
if removedRows > 0 {
|
||||
for _, expiredEntry := range expiredEntries {
|
||||
storeInstance.notify(Event{
|
||||
Type: EventDelete,
|
||||
Group: expiredEntry.group,
|
||||
Key: expiredEntry.key,
|
||||
Timestamp: time.Now(),
|
||||
})
|
||||
}
|
||||
}
|
||||
return removedRows, nil
|
||||
}
|
||||
|
||||
|
|
@ -1035,24 +1051,63 @@ func fieldsValueSeq(value string) iter.Seq[string] {
|
|||
}
|
||||
}
|
||||
|
||||
type expiredEntryRef struct {
|
||||
group string
|
||||
key string
|
||||
}
|
||||
|
||||
func listExpiredEntriesMatchingGroupPrefix(database schemaDatabase, groupPrefix string, cutoffUnixMilli int64) ([]expiredEntryRef, error) {
|
||||
var (
|
||||
rows *sql.Rows
|
||||
err error
|
||||
)
|
||||
if groupPrefix == "" {
|
||||
rows, err = database.Query(
|
||||
"SELECT "+entryGroupColumn+", "+entryKeyColumn+" FROM "+entriesTableName+" WHERE expires_at IS NOT NULL AND expires_at <= ? ORDER BY "+entryGroupColumn+", "+entryKeyColumn,
|
||||
cutoffUnixMilli,
|
||||
)
|
||||
} else {
|
||||
rows, err = database.Query(
|
||||
"SELECT "+entryGroupColumn+", "+entryKeyColumn+" FROM "+entriesTableName+" WHERE expires_at IS NOT NULL AND expires_at <= ? AND "+entryGroupColumn+" LIKE ? ESCAPE '^' ORDER BY "+entryGroupColumn+", "+entryKeyColumn,
|
||||
cutoffUnixMilli, escapeLike(groupPrefix)+"%",
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
expiredEntries := make([]expiredEntryRef, 0)
|
||||
for rows.Next() {
|
||||
var expiredEntry expiredEntryRef
|
||||
if err := rows.Scan(&expiredEntry.group, &expiredEntry.key); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
expiredEntries = append(expiredEntries, expiredEntry)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return expiredEntries, nil
|
||||
}
|
||||
|
||||
// purgeExpiredMatchingGroupPrefix deletes expired rows globally when
|
||||
// groupPrefix is empty, otherwise only rows whose group starts with the given
|
||||
// prefix.
|
||||
func purgeExpiredMatchingGroupPrefix(database schemaDatabase, groupPrefix string) (int64, error) {
|
||||
func purgeExpiredMatchingGroupPrefix(database schemaDatabase, groupPrefix string, cutoffUnixMilli int64) (int64, error) {
|
||||
var (
|
||||
deleteResult sql.Result
|
||||
err error
|
||||
)
|
||||
now := time.Now().UnixMilli()
|
||||
if groupPrefix == "" {
|
||||
deleteResult, err = database.Exec(
|
||||
"DELETE FROM "+entriesTableName+" WHERE expires_at IS NOT NULL AND expires_at <= ?",
|
||||
now,
|
||||
cutoffUnixMilli,
|
||||
)
|
||||
} else {
|
||||
deleteResult, err = database.Exec(
|
||||
"DELETE FROM "+entriesTableName+" WHERE expires_at IS NOT NULL AND expires_at <= ? AND "+entryGroupColumn+" LIKE ? ESCAPE '^'",
|
||||
now, escapeLike(groupPrefix)+"%",
|
||||
cutoffUnixMilli, escapeLike(groupPrefix)+"%",
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -511,9 +511,25 @@ func (storeTransaction *StoreTransaction) PurgeExpired() (int64, error) {
|
|||
return 0, err
|
||||
}
|
||||
|
||||
removedRows, err := purgeExpiredMatchingGroupPrefix(storeTransaction.sqliteTransaction, "")
|
||||
cutoffUnixMilli := time.Now().UnixMilli()
|
||||
expiredEntries, err := listExpiredEntriesMatchingGroupPrefix(storeTransaction.sqliteTransaction, "", cutoffUnixMilli)
|
||||
if err != nil {
|
||||
return 0, core.E("store.Transaction.PurgeExpired", "list expired rows", err)
|
||||
}
|
||||
|
||||
removedRows, err := purgeExpiredMatchingGroupPrefix(storeTransaction.sqliteTransaction, "", cutoffUnixMilli)
|
||||
if err != nil {
|
||||
return 0, core.E("store.Transaction.PurgeExpired", "delete expired rows", err)
|
||||
}
|
||||
if removedRows > 0 {
|
||||
for _, expiredEntry := range expiredEntries {
|
||||
storeTransaction.recordEvent(Event{
|
||||
Type: EventDelete,
|
||||
Group: expiredEntry.group,
|
||||
Key: expiredEntry.key,
|
||||
Timestamp: time.Now(),
|
||||
})
|
||||
}
|
||||
}
|
||||
return removedRows, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue