unexport the filesystem hooks for now to avoid introducing breaking changes

This commit is contained in:
Gani Georgiev
2026-08-21 22:58:14 +03:00
parent 0e9dcfe1ab
commit 654af12d17
7 changed files with 56 additions and 31 deletions
+2 -2
View File
@@ -6,8 +6,8 @@
- Added helper `filesystem` methods:
- `filesystem.NewWriter(key, opts)` to allow direct file create from an `io.Reader` value.
- `filesystem.OnNewWriter()` hook to allow listening for new/to-be-creaded files (app level equivalent `app.OnFilesystemNewWriter()` hook is also available).
- `filesystem.OnDelete()` hook to allow listening for deleted files (app level equivalent `app.OnFilesystemDelete()` hook is also available).
- `filesystem.OnNewWriter()` low-level hook to allow listening for new/to-be-creaded files _(app level equivalent hook is also available but not exposed for now to avoid introducing breaking changes)_.
- `filesystem.OnDelete()` low-level hook to allow listening for deleted files _(app level equivalent hook is also available but not exposed for now to avoid introducing breaking changes)_.
- Added new `DELETE /api/logs` endpoint and UI control to delete all logs without changing the `maxDays` retention setting.
+4 -4
View File
@@ -1266,14 +1266,14 @@ type App interface {
// Filesystem event hooks
// ---------------------------------------------------------------
// OnFilesystemNewWriter is a low level hook for app.NewFilesystem()
// onFilesystemNewWriter is an internal hook for app.NewFilesystem()
// instances that is triggered on every storage filesystem writer initialization
// (aka. whenever attempting to create a new file).
OnFilesystemNewWriter() *hook.Hook[*FilesystemNewWriterEvent]
onFilesystemNewWriter() *hook.Hook[*FilesystemNewWriterEvent]
// OnFilesystemDelete is a low level hook for app.NewFilesystem()
// onFilesystemDelete is an internal hook for app.NewFilesystem()
// instances that is triggered for every storage file delete call.
OnFilesystemDelete() *hook.Hook[*FilesystemDeleteEvent]
onFilesystemDelete() *hook.Hook[*FilesystemDeleteEvent]
// ---------------------------------------------------------------
// Realtime API event hooks
+17 -11
View File
@@ -50,7 +50,7 @@ import (
//
// 3. Stop listening for DELETED files.
//
// 4. Start listening for NEW storage files and mark all new files as excluded.
// 4. Start listening for NEW storage files and mark all new files from this point as "excluded".
//
// 5. Copy the logs database with VACUUM INTO, write it in the zip and mark it as "excluded".
//
@@ -142,8 +142,8 @@ func createZip(be *BackupEvent, tempZipPath string) error {
const tempFilesHookId = "__pbTempBackupFilesystemWatcher__"
defer func() {
// unbind again in cacase of an error
be.App.OnFilesystemDelete().Unbind(tempFilesHookId)
be.App.OnFilesystemNewWriter().Unbind(tempFilesHookId)
be.App.onFilesystemDelete().Unbind(tempFilesHookId)
be.App.onFilesystemNewWriter().Unbind(tempFilesHookId)
}()
zf, err := os.Create(tempZipPath)
@@ -170,8 +170,9 @@ func createZip(be *BackupEvent, tempZipPath string) error {
// init deleted files tracker
// ---------------------------------------------------------------
be.App.OnFilesystemDelete().Bind(&hook.Handler[*FilesystemDeleteEvent]{
Id: tempFilesHookId,
be.App.onFilesystemDelete().Bind(&hook.Handler[*FilesystemDeleteEvent]{
Id: tempFilesHookId,
Priority: -99,
Func: func(e *FilesystemDeleteEvent) error {
// note: the zip header name allow only forward slashes
zipPath := path.Join(LocalStorageDirName, e.FileKey)
@@ -214,8 +215,8 @@ func createZip(be *BackupEvent, tempZipPath string) error {
return err
}
// eageerly stop listenining for deleted files since we already have what we needed
be.App.OnFilesystemDelete().Unbind(tempFilesHookId)
// eagerly stop listening for deleted files since we already have what we needed
be.App.onFilesystemDelete().Unbind(tempFilesHookId)
be.App.Logger().Debug(
logPrefix+dataDBFilename+" copy completed",
@@ -235,12 +236,13 @@ func createZip(be *BackupEvent, tempZipPath string) error {
// init to-be-created files tracker
// ---------------------------------------------------------------
be.App.OnFilesystemNewWriter().Bind(&hook.Handler[*FilesystemNewWriterEvent]{
Id: tempFilesHookId,
be.App.onFilesystemNewWriter().Bind(&hook.Handler[*FilesystemNewWriterEvent]{
Id: tempFilesHookId,
Priority: -99,
Func: func(e *FilesystemNewWriterEvent) error {
if !be.App.Settings().S3.Enabled {
// mark for exclude even if the writer eventually fails
// (all record files have random name so collusions are unlikely)
// (all record files have random name so collisions are unlikely)
name := normalizePathExclude(filepath.Join(LocalStorageDirName, e.FileKey))
excluded.Set(name, struct{}{})
}
@@ -296,6 +298,10 @@ func copyFileToZip(w *zip.Writer, localPath string, zipPath string) error {
return err
}
if info.IsDir() {
return nil
}
h, err := zip.FileInfoHeader(info)
if err != nil {
return err
@@ -329,7 +335,7 @@ func copyDirToZip(w *zip.Writer, fsys fs.FS, excludedPrefixes *store.Store[strin
// skip excluded prefixes
if excludedPrefixes != nil {
check := normalizePathExclude(name)
prefixes := excludedPrefixes.Keys() // refetch in case to avoid races
prefixes := excludedPrefixes.Keys() // refetch to avoid races
for _, prefix := range prefixes {
if strings.HasPrefix(check, prefix) {
if d.IsDir() {
+16 -12
View File
@@ -150,8 +150,8 @@ type BaseApp struct {
onMailerRecordAuthAlertSend *hook.Hook[*MailerRecordEvent]
// filesystem event hooks
onFilesystemNewWriter *hook.Hook[*FilesystemNewWriterEvent]
onFilesystemDelete *hook.Hook[*FilesystemDeleteEvent]
_onFilesystemNewWriter *hook.Hook[*FilesystemNewWriterEvent]
_onFilesystemDelete *hook.Hook[*FilesystemDeleteEvent]
// realtime api event hooks
onRealtimeConnectRequest *hook.Hook[*RealtimeConnectRequestEvent]
@@ -302,8 +302,12 @@ func (app *BaseApp) initHooks() {
app.onMailerRecordAuthAlertSend = &hook.Hook[*MailerRecordEvent]{}
// filesystem event hooks
app.onFilesystemNewWriter = &hook.Hook[*FilesystemNewWriterEvent]{}
app.onFilesystemDelete = &hook.Hook[*FilesystemDeleteEvent]{}
//
// intentionally not exposed since the events are too "chatty" and
// can cause unnecessery userland tests breaking changes;
// reevaluate once refactoring the file_field
app._onFilesystemNewWriter = &hook.Hook[*FilesystemNewWriterEvent]{}
app._onFilesystemDelete = &hook.Hook[*FilesystemDeleteEvent]{}
// realtime API event hooks
app.onRealtimeConnectRequest = &hook.Hook[*RealtimeConnectRequestEvent]{}
@@ -743,26 +747,26 @@ func (app *BaseApp) NewFilesystem() (fsys *filesystem.System, err error) {
}
// attach delete hook
if app.onFilesystemDelete.Length() > 0 {
if app._onFilesystemDelete.Length() > 0 {
fsys.OnDelete().BindFunc(func(originalEvent *filesystem.DeleteEvent) error {
appEvent := new(FilesystemDeleteEvent)
appEvent.DeleteEvent = originalEvent
appEvent.App = app
return app.onFilesystemDelete.Trigger(appEvent, func(fde *FilesystemDeleteEvent) error {
return app._onFilesystemDelete.Trigger(appEvent, func(fde *FilesystemDeleteEvent) error {
return originalEvent.Next()
})
})
}
// attach write hook
if app.onFilesystemNewWriter.Length() > 0 {
if app._onFilesystemNewWriter.Length() > 0 {
fsys.OnNewWriter().BindFunc(func(originalEvent *filesystem.NewWriterEvent) error {
appEvent := new(FilesystemNewWriterEvent)
appEvent.NewWriterEvent = originalEvent
appEvent.App = app
return app.onFilesystemNewWriter.Trigger(appEvent, func(fwe *FilesystemNewWriterEvent) error {
return app._onFilesystemNewWriter.Trigger(appEvent, func(fwe *FilesystemNewWriterEvent) error {
return originalEvent.Next()
})
})
@@ -1063,12 +1067,12 @@ func (app *BaseApp) OnMailerRecordAuthAlertSend(tags ...string) *hook.TaggedHook
// Filesystem event hooks
// -------------------------------------------------------------------
func (app *BaseApp) OnFilesystemNewWriter() *hook.Hook[*FilesystemNewWriterEvent] {
return app.onFilesystemNewWriter
func (app *BaseApp) onFilesystemNewWriter() *hook.Hook[*FilesystemNewWriterEvent] {
return app._onFilesystemNewWriter
}
func (app *BaseApp) OnFilesystemDelete() *hook.Hook[*FilesystemDeleteEvent] {
return app.onFilesystemDelete
func (app *BaseApp) onFilesystemDelete() *hook.Hook[*FilesystemDeleteEvent] {
return app._onFilesystemDelete
}
// -------------------------------------------------------------------
+1 -1
View File
@@ -1613,7 +1613,7 @@ func TestHooksBindsCount(t *testing.T) {
vm := goja.New()
hooksBinds(app, vm, nil)
testBindsCount(vm, "this", 84, t)
testBindsCount(vm, "this", 82, t)
}
func TestHooksBinds(t *testing.T) {
+15
View File
@@ -549,6 +549,21 @@ func NewTestAppWithConfig(config core.BaseAppConfig) (*TestApp, error) {
Priority: -99999,
})
// t.OnFilesystemDelete().Bind(&hook.Handler[*core.FilesystemDeleteEvent]{
// Func: func(e *core.FilesystemDeleteEvent) error {
// t.registerEventCall("OnFilesystemDelete")
// return e.Next()
// },
// Priority: -99999,
// })
// t.OnFilesystemNewWriter().Bind(&hook.Handler[*core.FilesystemNewWriterEvent]{
// Func: func(e *core.FilesystemNewWriterEvent) error {
// t.registerEventCall("OnFilesystemNewWriter")
// return e.Next()
// },
// Priority: -99999,
// })
t.OnRealtimeConnectRequest().Bind(&hook.Handler[*core.RealtimeConnectRequestEvent]{
Func: func(e *core.RealtimeConnectRequestEvent) error {
t.registerEventCall("OnRealtimeConnectRequest")
+1 -1
View File
@@ -482,7 +482,7 @@ func (s *System) DeletePrefix(prefix string) []error {
// A trailing slash will be appended to a non-empty dir string argument
// to ensure that the checked prefix is a "directory".
//
// Returns "false" in case the has at least one file, otherwise - "true".
// Returns "false" in case it has at least one file, otherwise - "true".
func (s *System) IsEmptyDir(dir string) bool {
if dir != "" && !strings.HasSuffix(dir, "/") {
dir += "/"