This repository was archived by the owner on Dec 22, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 100
PERL-791 Change stream support #151
Closed
phaylon
wants to merge
23
commits into
mongodb-labs:master
from
shadow-dot-cat:phaylon/PERL-791-fixed
Closed
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
6373104
PERL-791 Change stream support
phaylon e32fd12
adjusted to use Safe::Isa
phaylon 5b769fc
Added to MongoDB::ChangeStream
phaylon 9a323f0
Don't return undef as per Perl::Critic
phaylon 681be3d
Enable raising of MongoDB::CursorNotFoundError instead of just MongoD…
phaylon a7d1434
Added test for MongoDB::ChangeStream reconnections on MongoDB::Cursor…
phaylon 294585d
Adjust MongoDB::Error docs to include ::InvalidOperationError and mov…
phaylon 3f28048
Add ->_is_resumable() flag to MongoDB::Errors indicating if an error …
phaylon 9b034d8
Change MongoDB::ChangeStream to use MongoDB::Error->is_resumable() fo…
phaylon 1e9d72c
Add types to attributes in MongoDB::ChangeStream
phaylon cfdbd30
Rename ChangeStream->_cursor to ->_result
phaylon 3ba03db
Remove non-existant resume_token builder in ChangeStream
phaylon d97dffc
Rename ChangeStream->options to ->aggregation_options
phaylon 9b2a75f
Removed leftover unused client argument to ChangeStream construction …
phaylon c147c70
Removed unused variable
phaylon 8aa871e
Removed default empty array/hash ref constructs for pipeline/options …
phaylon 4622361
Removed cursorType from Op::_Aggregate
phaylon 0a581e6
Fixed ChangeStream->next documentation
phaylon 5fa5265
Removed temporary for change _id
phaylon da8f577
explicitly return undef instead of nothing when ChangeStream->next ha…
phaylon c8dd4bb
Fixed synopsis for ChangeStream
phaylon 27289bf
Fixed usage example in ChangeStream->watch
phaylon fa7dde8
Add note about where to obtain resumeAfter token to Collection->watch…
phaylon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,199 @@ | ||
| # | ||
| # Copyright 2009-2018 MongoDB, Inc. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| # | ||
|
|
||
| use strict; | ||
| use warnings; | ||
| package MongoDB::ChangeStream; | ||
|
|
||
| # ABSTRACT: A stream providing update information for collections. | ||
|
|
||
| use version; | ||
| our $VERSION = 'v1.999.0'; | ||
|
|
||
| use Moo; | ||
| use Try::Tiny; | ||
| use MongoDB::Cursor; | ||
| use MongoDB::Op::_Aggregate; | ||
| use MongoDB::Error; | ||
| use Safe::Isa; | ||
| use MongoDB::_Types qw( | ||
| MongoDBCollection | ||
| ArrayOfHashRef | ||
| ); | ||
| use Types::Standard qw( | ||
| InstanceOf | ||
| HashRef | ||
| Str | ||
| ); | ||
|
|
||
| use namespace::clean -except => 'meta'; | ||
|
|
||
| has _result => ( | ||
| is => 'rw', | ||
| isa => InstanceOf['MongoDB::QueryResult'], | ||
| lazy => 1, | ||
| builder => '_build_result', | ||
| clearer => '_clear_result', | ||
| ); | ||
|
|
||
| has collection => ( | ||
| is => 'ro', | ||
| isa => MongoDBCollection, | ||
| required => 1, | ||
| ); | ||
|
|
||
| has aggregation_options => ( | ||
| is => 'ro', | ||
| isa => HashRef, | ||
| ); | ||
|
|
||
| has pipeline => ( | ||
| is => 'ro', | ||
| isa => ArrayOfHashRef, | ||
| required => 1, | ||
| ); | ||
|
|
||
| has full_document => ( | ||
| is => 'ro', | ||
| isa => Str, | ||
| predicate => '_has_full_document', | ||
| ); | ||
|
|
||
| has _resume_token => ( | ||
| is => 'rw', | ||
| init_arg => 'resume_after', | ||
| predicate => '_has_resume_token', | ||
| lazy => 1, | ||
| ); | ||
|
|
||
| sub BUILD { | ||
| my ($self) = @_; | ||
|
|
||
| # starting point is construction time instead of first next call | ||
| $self->_result; | ||
| } | ||
|
|
||
| sub _build_result { | ||
| my ($self) = @_; | ||
|
|
||
| my @pipeline = @{ $self->pipeline }; | ||
| @pipeline = ( | ||
| {'$changeStream' => { | ||
| ($self->_has_full_document | ||
| ? (fullDocument => $self->full_document) | ||
| : () | ||
| ), | ||
| ($self->_has_resume_token | ||
| ? (resumeAfter => $self->_resume_token) | ||
| : () | ||
| ), | ||
| }}, | ||
| @pipeline, | ||
| ); | ||
|
|
||
| return $self->collection->aggregate( | ||
| \@pipeline, | ||
| $self->aggregation_options, | ||
| ); | ||
| } | ||
|
|
||
| =head1 STREAM METHODS | ||
|
|
||
| =cut | ||
|
|
||
| =head2 next | ||
|
|
||
| $change_stream = $collection->watch(...); | ||
| $change = $change_stream->next; | ||
|
|
||
| Waits for the next change in the collection and returns it. | ||
|
|
||
| B<Note>: This method will wait for the amount of milliseconds passed | ||
| as C<maxAwaitTimeMS> to L<MongoDB::Collection/watch> or the server's | ||
| default wait-time. It will not wait indefinitely. | ||
|
|
||
| =cut | ||
|
|
||
| sub next { | ||
| my ($self) = @_; | ||
|
|
||
| my $change; | ||
| my $retried; | ||
| while (1) { | ||
| last if try { | ||
| $change = $self->_result->next; | ||
| 1 # successfully fetched result | ||
| } | ||
| catch { | ||
| my $error = $_; | ||
| if ( | ||
| not($retried) | ||
| and $error->$_isa('MongoDB::Error') | ||
| and $error->_is_resumable | ||
| ) { | ||
| $retried = 1; | ||
| $self->_result($self->_build_result); | ||
| } | ||
| else { | ||
| die $error; | ||
| } | ||
| 0 # failed, cursor was rebuilt | ||
| }; | ||
| } | ||
|
|
||
| # this differs from drivers that block indefinitely. we have to | ||
| # deal with the situation where no results are available. | ||
| if (not defined $change) { | ||
| return undef; | ||
| } | ||
|
|
||
| if (exists $change->{_id}) { | ||
| $self->_resume_token($change->{_id}); | ||
| return $change; | ||
| } | ||
| else { | ||
| MongoDB::InvalidOperationError->throw( | ||
| "Cannot provide resume functionality when the ". | ||
| "resume token is missing"); | ||
| } | ||
| } | ||
|
|
||
| 1; | ||
|
|
||
| =head1 SYNOPSIS | ||
|
|
||
| $stream = $collection->watch( $pipeline, $options ); | ||
| while(1) { | ||
|
|
||
| # This inner loop will only iterate until there are no more | ||
| # changes available. | ||
| while (my $change = $stream->next) { | ||
| ... | ||
| } | ||
| } | ||
|
|
||
| =head1 DESCRIPTION | ||
|
|
||
| This class models change stream results as returned by the | ||
| L<MongoDB::Collection/watch> method. | ||
|
|
||
| =head1 SEE ALSO | ||
|
|
||
| The L<Change Streams manual section|https://docs.mongodb.com/manual/changeStreams/>. | ||
|
|
||
| The L<Change Streams specification|https://github.com/mongodb/specifications/blob/master/source/change-streams.rst>. | ||
|
|
||
| =cut |
This file contains hidden or 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 hidden or 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.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add to this that it must be the
_idfrom a document returned from calling next on the ChangeStream object.