@ -17,6 +17,11 @@ import (
"git.mleku.dev/mleku/nostr/utils/units"
"git.mleku.dev/mleku/nostr/utils/units"
)
)
// Flusher interface for HTTP streaming
type flusher interface {
Flush ( )
}
// Export the complete database of stored events to an io.Writer in line structured minified
// Export the complete database of stored events to an io.Writer in line structured minified
// JSON. Supports both legacy and compact event formats.
// JSON. Supports both legacy and compact event formats.
func ( d * D ) Export ( c context . Context , w io . Writer , pubkeys ... [ ] byte ) {
func ( d * D ) Export ( c context . Context , w io . Writer , pubkeys ... [ ] byte ) {
@ -24,11 +29,18 @@ func (d *D) Export(c context.Context, w io.Writer, pubkeys ...[]byte) {
evB := make ( [ ] byte , 0 , units . Mb )
evB := make ( [ ] byte , 0 , units . Mb )
evBuf := bytes . NewBuffer ( evB )
evBuf := bytes . NewBuffer ( evB )
// Get flusher for HTTP streaming if available
var f flusher
if fl , ok := w . ( flusher ) ; ok {
f = fl
}
// Performance tracking
// Performance tracking
startTime := time . Now ( )
startTime := time . Now ( )
var eventCount , bytesWritten int64
var eventCount , bytesWritten int64
lastLogTime := startTime
lastLogTime := startTime
const logInterval = 5 * time . Second
const logInterval = 5 * time . Second
const flushInterval = 100 // Flush every N events
log . I . F ( "export: starting export operation" )
log . I . F ( "export: starting export operation" )
@ -109,6 +121,11 @@ func (d *D) Export(c context.Context, w io.Writer, pubkeys ...[]byte) {
eventCount ++
eventCount ++
ev . Free ( )
ev . Free ( )
// Flush periodically for HTTP streaming
if f != nil && eventCount % flushInterval == 0 {
f . Flush ( )
}
// Progress logging every logInterval
// Progress logging every logInterval
if time . Since ( lastLogTime ) >= logInterval {
if time . Since ( lastLogTime ) >= logInterval {
elapsed := time . Since ( startTime )
elapsed := time . Since ( startTime )
@ -169,6 +186,11 @@ func (d *D) Export(c context.Context, w io.Writer, pubkeys ...[]byte) {
eventCount ++
eventCount ++
ev . Free ( )
ev . Free ( )
// Flush periodically for HTTP streaming
if f != nil && eventCount % flushInterval == 0 {
f . Flush ( )
}
// Progress logging every logInterval
// Progress logging every logInterval
if time . Since ( lastLogTime ) >= logInterval {
if time . Since ( lastLogTime ) >= logInterval {
elapsed := time . Since ( startTime )
elapsed := time . Since ( startTime )
@ -186,6 +208,11 @@ func (d *D) Export(c context.Context, w io.Writer, pubkeys ...[]byte) {
return
return
}
}
// Final flush
if f != nil {
f . Flush ( )
}
// Final export summary
// Final export summary
elapsed := time . Since ( startTime )
elapsed := time . Since ( startTime )
eventsPerSec := float64 ( eventCount ) / elapsed . Seconds ( )
eventsPerSec := float64 ( eventCount ) / elapsed . Seconds ( )
@ -244,6 +271,11 @@ func (d *D) Export(c context.Context, w io.Writer, pubkeys ...[]byte) {
eventCount ++
eventCount ++
ev . Free ( )
ev . Free ( )
// Flush periodically for HTTP streaming
if f != nil && eventCount % flushInterval == 0 {
f . Flush ( )
}
// Progress logging every logInterval
// Progress logging every logInterval
if time . Since ( lastLogTime ) >= logInterval {
if time . Since ( lastLogTime ) >= logInterval {
elapsed := time . Since ( startTime )
elapsed := time . Since ( startTime )
@ -261,6 +293,11 @@ func (d *D) Export(c context.Context, w io.Writer, pubkeys ...[]byte) {
}
}
}
}
// Final flush
if f != nil {
f . Flush ( )
}
// Final export summary for pubkey export
// Final export summary for pubkey export
elapsed := time . Since ( startTime )
elapsed := time . Since ( startTime )
eventsPerSec := float64 ( eventCount ) / elapsed . Seconds ( )
eventsPerSec := float64 ( eventCount ) / elapsed . Seconds ( )