-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
services, design: Propose and implement 21-split-segmenter (#270)
Signed-off-by: Xuanwo <github@xuanwo.io>
- Loading branch information
Showing
11 changed files
with
200 additions
and
167 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
--- | ||
author: Xuanwo <github@xuanwo.io> | ||
status: candidate | ||
updated_at: 2020-04-27 | ||
--- | ||
|
||
# Proposal: Split Segmenter | ||
|
||
## Background | ||
|
||
In proposal [18-return-segment-interface-instead], we introduced `segment.Segmenter` interface, but also introduce a new problem: user don't know which type of segment that service supported. | ||
|
||
In the `Rationale` section of [18-return-segment-interface-instead], we have already discussed two implementations: | ||
|
||
1. `OffsetBasedSegmenter` vs `IndexBasedSegmenter` | ||
2. `WriteSegmentViaIndex` vs `WriteSegmentViaOffset` | ||
|
||
We said: | ||
|
||
> No.1 implementation's problem is these add too much work for services to support both of them. | ||
But maybe this is the way, we can build new segmenter upon this idea. | ||
|
||
## Proposal | ||
|
||
Based on the idea of `OffsetBasedSegmenter` and `IndexBasedSegmenter`, I propose following changes: | ||
|
||
Add new interface `IndexSegmenter` that implement following functions: | ||
|
||
- `InitIndexSegment(path string, pairs ...*types.Pair) (seg segment.Segment, err error)` | ||
- `WriteIndexSegment(seg segment.Segment, r io.Reader, index int, size int64, pairs ...*types.Pair) (err error)` | ||
- `CompleteSegment(seg segment.Segment, pairs ...*types.Pair) (err error)` | ||
- `AbortSegment(seg segment.Segment, pairs ...*types.Pair) (err error)` | ||
|
||
Extract `CompleteSegment` and `AbortSegment` into a non-exported interface `segmenter`. | ||
|
||
Embed `segmenter` into `IndexSegmenter`, `DirSegmentsLister` and `PrefixSegmentsLister` | ||
|
||
Remove `Segmenter` | ||
|
||
### Add new interface `IndexSegmenter` | ||
|
||
It's easy to find out that we don't need to implement an entire new segmenter interface. After introducing `segment.Segmenter` interface, we can reuse already implemented `CompleteSegment` and `AbortSegment`. | ||
|
||
After this change, the workload for service implementer reduced as the same. If new segment method needs to implemented, we only need to add `OffsetSegmenter`. | ||
|
||
### Extract non-exported interface and embed into others | ||
|
||
We already added `DirSegmentsLister` and `PrefixSegmentsLister`, but list only interface is not useful, we always need to convert to `Segmenter`. After extracting `CompleteSegment` and `AbortSegment` into a non-exported interface, we can make `DirSegmentsLister` and `PrefixSegmentsLister` more useful. | ||
|
||
### Remove `Segmenter` | ||
|
||
Yes, I know, I introduced an API breaking changes here. | ||
|
||
I'm sorry, but I don't have the time and energy to maintain both v1 and v2 for now. Since [storage] is nearly no one except me used, I think it's safe to introduce this change here and not break others. | ||
|
||
I'm aware the risk, and I will be responsible for this. | ||
|
||
## Rationale | ||
|
||
None. | ||
|
||
## Compatibility | ||
|
||
All API call related `Segmenter` will be borken. | ||
|
||
## Implementation | ||
|
||
Most of the work would be done by the author of this proposal. | ||
|
||
[18-return-segment-interface-instead]: (./18-return-segment-interface-instead.md) | ||
[storage]: https://github.com/Xuanwo/storage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package storage | ||
|
||
import ( | ||
"context" | ||
"io" | ||
|
||
"github.com/Xuanwo/storage/pkg/segment" | ||
"github.com/Xuanwo/storage/types" | ||
) | ||
|
||
type segmenter interface { | ||
// CompleteSegment will complete a segment and merge them into a File. | ||
// | ||
// Implementer: | ||
// - SHOULD return error while caller call CompleteSegment without init. | ||
// Caller: | ||
// - SHOULD call InitIndexSegment before CompleteSegment. | ||
CompleteSegment(seg segment.Segment, pairs ...*types.Pair) (err error) | ||
// CompleteSegmentWithContext will complete a segment and merge them into a File. | ||
CompleteSegmentWithContext(ctx context.Context, seg segment.Segment, pairs ...*types.Pair) (err error) | ||
// AbortSegment will abort a segment. | ||
// | ||
// Implementer: | ||
// - SHOULD return error while caller call AbortSegment without init. | ||
// Caller: | ||
// - SHOULD call InitIndexSegment before AbortSegment. | ||
AbortSegment(seg segment.Segment, pairs ...*types.Pair) (err error) | ||
// AbortSegmentWithContext will abort a segment. | ||
AbortSegmentWithContext(ctx context.Context, seg segment.Segment, pairs ...*types.Pair) (err error) | ||
} | ||
|
||
// DirSegmentsLister is used for directory based storage service to list segments under a dir. | ||
type DirSegmentsLister interface { | ||
segmenter | ||
|
||
// ListDirSegments will list segments via dir. | ||
ListDirSegments(path string, pairs ...*types.Pair) (err error) | ||
// ListDirSegmentsWithContext will list segments via dir. | ||
ListDirSegmentsWithContext(ctx context.Context, path string, pairs ...*types.Pair) (err error) | ||
} | ||
|
||
// PrefixSegmentsLister is used for prefix based storage service to list segments under a prefix. | ||
type PrefixSegmentsLister interface { | ||
segmenter | ||
|
||
// ListSegments will list segments. | ||
// | ||
// Implementer: | ||
// - If prefix == "", services should return all segments. | ||
ListPrefixSegments(prefix string, pairs ...*types.Pair) (err error) | ||
// ListSegmentsWithContext will list segments. | ||
ListPrefixSegmentsWithContext(ctx context.Context, prefix string, pairs ...*types.Pair) (err error) | ||
} | ||
|
||
// IndexSegmenter is the interface for index based segment. | ||
type IndexSegmenter interface { | ||
segmenter | ||
|
||
// InitIndexSegment will init an index based segment | ||
InitIndexSegment(path string, pairs ...*types.Pair) (seg segment.Segment, err error) | ||
// InitIndexSegmentWithContext will init an index based segment | ||
InitIndexSegmentWithContext(ctx context.Context, path string, pairs ...*types.Pair) (seg segment.Segment, err error) | ||
|
||
// WriteIndexSegment will write a part into an index based segment. | ||
WriteIndexSegment(seg segment.Segment, r io.Reader, index int, size int64, pairs ...*types.Pair) (err error) | ||
// WriteIndexSegmentWithContext will write a part into an index based segment. | ||
WriteIndexSegmentWithContext(ctx context.Context, seg segment.Segment, r io.Reader, index int, size int64, pairs ...*types.Pair) (err error) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.