docs: add durable-streams support and update persistence documentation#47
docs: add durable-streams support and update persistence documentation#47jilio wants to merge 3 commits into
Conversation
- Add 🌍 Remote storage feature to README - Add Remote Storage section with durable-streams example - Add Storage Backends table documenting all available options - Update StoredEvent structure to use Offset type instead of Position - Add SQLite and Durable-Streams store usage examples - Update EventStore interface to new Append/Read signatures - Add SubscriptionStore and EventStoreStreamer interfaces - Update all replay examples to use eventbus.OffsetOldest Closes #42 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add reference to Electric's announcement blog post explaining the Durable Streams protocol specification. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Pull Request ReviewThis PR successfully updates the documentation to reflect the new offset-native ✅ Strengths1. Comprehensive Documentation Updates
2. PERSISTENCE.md Improvements
3. Accuracy & Consistency
4. Code Quality
📝 Minor Observations1. Link Accuracy (docs/PERSISTENCE.md:121) [durable-streams](https://github.com/jilio/durable-streams)However, the actual package comment in // durable-streams servers (https://github.com/durable-streams/durable-streams).Recommendation: Verify which organization owns the durable-streams repository. If it's 2. Import Path Clarification (docs/PERSISTENCE.md:122, 156) import (
eventbus "github.com/jilio/ebu"
"github.com/jilio/ebu/stores/durablestream"
)This is correct and matches the actual package structure. Well done! 3. Example Completeness 🎯 Verification Against Issue #42
All acceptance criteria met! 🔒 Security & Performance
📊 Test CoverageNo code changes, so no test coverage impact. All documented APIs have corresponding test coverage in the codebase (verified via grep). ✅ Final RecommendationAPPROVE - This PR is ready to merge. The documentation accurately reflects the implementation, provides clear examples, and successfully addresses all requirements from issue #42. The only minor item is verifying the durable-streams GitHub organization link, which can be addressed in a follow-up if needed or before merge. Great work maintaining comprehensive, accurate documentation! 🎉 |
Pull Request Review: Documentation Updates for Durable-Streams SupportOverall Assessment✅ APPROVED - This is a high-quality documentation update that accurately reflects the new offset-native interface and durable-streams support. The changes are well-structured, comprehensive, and follow Go documentation best practices. Strengths1. Accuracy ✅
2. Completeness ✅
3. Clarity ✅
4. Consistency ✅
Detailed FeedbackREADME.md ChangesExcellent additions:
Minor observation:
docs/PERSISTENCE.md ChangesStrong updates:
Particularly good: // Read returns events starting after the given offset
// Use OffsetOldest to read from the beginning
// Use limit > 0 to limit results, or 0 for no limit
Read(ctx context.Context, from Offset, limit int) ([]*StoredEvent, Offset, error)The interface documentation is clear about behavior and return values. Code Quality AssessmentDocumentation Standards ✅
Migration Guidance ✅The PR effectively guides users through the interface change:
This is clearly documented with side-by-side examples. Test Coverage 📊Per CLAUDE.md requirements, this is a documentation-only change with no code changes, so test coverage requirements are N/A. Potential Issues1. Durable-Streams URL
|
| Requirement | Status | Notes |
|---|---|---|
| Go fmt | N/A | Documentation only |
| Tests pass | ✅ | PR description confirms no code changes |
| Test coverage | N/A | Documentation only |
| Go idioms | ✅ | Examples follow Go best practices |
| Options pattern | ✅ | Shown in durablestream examples |
| Simple implementations | ✅ | Examples are focused and clear |
Recommendations
High Priority
- Verify durable-streams links - Ensure all URLs point to the correct/official repositories
Medium Priority
- Add migration section - Create a dedicated "Migrating from v1 to v2" section
- Version compatibility note - Clarify which version introduced the offset-based interface
Low Priority (Nice to have)
- Add troubleshooting section - Common issues with remote storage
- Performance benchmarks - Comparison between local and remote stores
- Example repo link - Link to a complete working example repository
Conclusion
This is excellent documentation work that:
- ✅ Accurately reflects the codebase
- ✅ Provides clear migration guidance
- ✅ Includes practical, runnable examples
- ✅ Maintains consistency throughout
- ✅ Follows Go documentation best practices
The PR is ready to merge pending verification of the durable-streams repository links.
Great work on maintaining such thorough and clear documentation! 🎉
Closes #42 ✅
Update link to point to the official durable-streams organization repository instead of the fork. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Pull Request Review: Documentation Updates for Durable-Streams SupportThank you for this comprehensive documentation update! This is a well-structured PR that adds important documentation for the new offset-based persistence interface and remote storage capabilities. Here's my detailed review: ✅ Strengths
🔍 Areas for Improvement1. Documentation-Only Changes ClaimIssue: The PR description states "No code changes - documentation only", but this PR is documenting new functionality that was added in previous PRs. Recommendation: Update the PR description to clarify:
2. PostgreSQL Example CompletenessLocation: Issues Found:
Recommendation: // Add schema definition before the example
/*
CREATE TABLE events (
position BIGSERIAL PRIMARY KEY,
type TEXT NOT NULL,
data JSONB NOT NULL,
timestamp TIMESTAMP WITH TIME ZONE NOT NULL
);
CREATE TABLE subscriptions (
subscription_id TEXT PRIMARY KEY,
position BIGINT NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);
*/
// Fix function signature on line 406:
func (p *PostgresStore) Append(ctx context.Context, event *eventbus.Event) (eventbus.Offset, error) {
var position int64
err := p.db.QueryRowContext(ctx, `
INSERT INTO events (type, data, timestamp)
VALUES ($1, $2, $3)
RETURNING position
- `, event.Type, event.Data, event.Timestamp).Scan(&position)
+ `, event.Type, event.Data, time.Now()).Scan(&position)
if err != nil {
return "", err
}
return eventbus.Offset(strconv.FormatInt(position, 10)), nil
}
// Add error handling for offset parsing:
func (p *PostgresStore) Read(ctx context.Context, from eventbus.Offset, limit int) ([]*eventbus.StoredEvent, eventbus.Offset, error) {
var fromPos int64
if from != eventbus.OffsetOldest {
- fromPos, _ = strconv.ParseInt(string(from), 10, 64)
+ var err error
+ fromPos, err = strconv.ParseInt(string(from), 10, 64)
+ if err != nil {
+ return nil, from, fmt.Errorf("invalid offset: %w", err)
+ }
}
// ... rest of implementation
}3. Durable-Streams Store DetailsLocation: Missing Information:
Recommendation: Add a note about offset handling: Durable-streams features:
- HTTP-based protocol for distributed systems
- Automatic retries with exponential backoff
- Configurable timeouts
- Server-assigned opaque offsets
+ - **Important:** If the server doesn't include per-event offsets in responses,
+ synthetic offsets are generated for uniqueness within a Read call. Always use
+ the `nextOffset` returned by Read() for reliable resumption, not individual
+ event offsets from a response without embedded offset fields.4. Minor Consistency IssuesLocation: - // Replay events from the beginning
+ // Replay all events from the beginningLocation: // After a restart, subscriptions automatically resume from last offset
eventbus.SubscribeWithReplay(ctx, bus, "order-processor",
func(event OrderCreatedEvent) {
processOrder(event)
// Offset automatically tracked across restarts via remote server
})🔒 Security ConsiderationsGood: No security issues found in the documentation examples. Note: The SQLite store implementation properly validates paths to prevent injection (stores/sqlite/store.go:53-55), which is good practice. 🎯 Performance ConsiderationsGood:
Suggestion: Consider adding a performance tip in the SQLite section: ### Performance Tips
For high-throughput scenarios:
- Use `WithStreamBatchSize(1000)` for large replays to reduce memory usage
- Enable connection pooling with `db.SetMaxOpenConns()` for concurrent workloads
- Consider using `PRAGMA synchronous = NORMAL` (already default) for better write performance✅ Test Coverage AssessmentBased on the file structure and code review:
Note: This is a documentation-only PR, so no new tests are required. The documented interfaces match the tested implementations. 📝 Recommendations SummaryMust Fix:
Should Fix:
Nice to Have:
🎉 ConclusionThis is a high-quality documentation update that significantly improves the persistence documentation. The updates are accurate, comprehensive, and well-organized. With the minor fixes suggested above (mainly adding error handling to the PostgreSQL example), this will be an excellent resource for users. The documentation successfully:
Recommendation: Approve with minor changes requested for the PostgreSQL example error handling. Great work on this documentation! 🚀 Reviewed by Claude Sonnet 4.5 - Automated PR Review |
|
Superseded by #48 which includes both the durablestream rewrite for protocol conformance and the documentation updates. |
Summary
Changes
README.md
OffsetOldestdocs/PERSISTENCE.md
StoredEventstructure to useOffsettype instead ofPositionstores/sqlite)EventStoreinterface to newAppend/ReadsignaturesSubscriptionStoreandEventStoreStreamerinterfaceseventbus.OffsetOldestTest plan
Closes #42
🤖 Generated with Claude Code