-
Notifications
You must be signed in to change notification settings - Fork 266
PHPLIB-547: Add helpers to list database and collection names #758
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Return Values | ||
------------- | ||
|
||
A generator containing the name of each database on the server. |
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.
Can we link to the PHP class with:
:php:`Generator <class.generator.php>`
Also, would it be more correct to write "a generator that yields that name of each..." or "a generator, which yields...", rather than "containing"?
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.
Since this hasn't been changed yet, please see my other comment about only documenting a Traversable or Iterator. There may not be any reason to inform users that we're using Generators internally.
src/Client.php
Outdated
* @throws InvalidArgumentException for parameter/option parsing errors | ||
* @throws DriverRuntimeException for other driver errors (e.g. connection errors) | ||
*/ | ||
public function listDatabaseNames(array $options = []) |
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.
Do we want to use : Generator
as a return type hint here, or are we putting off adding those to our public API until we do so across the board?
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.
I've started adding them to new methods, but forgot them in this case. I added type hints now.
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.
Just left a related comment about this on the Database::listCollectionNames
method. Perhaps it makes sense to only document that we return a Traversable or Iterator.
src/Command/ListDatabases.php
Outdated
throw new UnexpectedValueException('listDatabases command did not return a "databases" array'); | ||
} | ||
|
||
// Using array_column here emulates nameOnly behavior for servers that don't support it and ensures a consistent return type |
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.
This is what I'd suggest moving to ListDatabaseNames, which currently just yields from this result directly. I suppose doing yield from array_column($result['databases'], 'name')
would be cheaper than using the CallbackIterator, especially since the result is already an array (unlike a potentially large listCollections response, where iterators may conserve memory).
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.
array_column
won't work here since the ListCollections
command returns a CachingIterator over the result cursor, which is why I added the iterator on top of that.
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.
We're talking about ListDatabases here, though, which always returns an array. Am I misunderstanding?
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.
Apologies, I got confused. ListDatabaseNames
uses array_column
since we're already dealing with an array.
src/Database.php
Outdated
* | ||
* @see ListCollectionNames::__construct() for supported options | ||
* @param array $options | ||
* @return Generator |
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.
In the interest of a conservative public API, I wonder if we should just document that we return a Traversable or Iterator. This would be similar to how I only documented a generic CollectionInfoIterator return type for the listCollections
method. Granted, that was the abstract the user from thinking about legacy and cursor-based responses, but it was also suggesting that the only thing they need care about was that the current element is a CollectionInfo object.
Generator has additional methods like send()
that I expect would have no use, so the fact that we happen to use a generator here seems like an implementation detail best not revealed.
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.
Generators can only be iterated once and can't be rewound, so I think the distinction is important to make sure people don't expect to repeatedly iterate over the same list of names.
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.
Ah, good point. That sounds like a possible deviation from the rewindable iterators returned by listDatabases
and listCollections
, though. Is it possible to wrap the generator with our CachingIterator. That would save users from having to ever care about this.
If we do make this change, I would then suggest we document an Iterator return value, since Traversable is not inherently rewindable.
Two side notes:
- 52df7a1 refactored our CachingIterator to use IteratorIterator instead of Generators, but I believe it forgot to update comments in the file that still refer to
yield
. I opened a PR to correct this: Remove mention of Generator in CachingIterator comments #763 - I just found https://github.com/bpolaszek/rewindable-generator, which is a project that addresses this issue with Generators, but it unfortunately uses SPL's CachingIterator, which has its own problems (see this blog comment, which I found a while ago in this tweet). As such, it actually breaks if you don't fully iterator the Generator before rewinding, which is something our own CachingIterator addresses (an early
rewind()
exhausts the inner iterator).
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.
Good point. ListCollectionNames
now returns the CallbackIterator
directly since we already have a CachingIterator
below. ListDatabaseNames
returns an ArrayIterator
to iterate over the array of names. This can then always be changed to return a CachingIterator
or other iterator should the listDatabases
command ever be changed to returning a cursor.
src/Client.php
Outdated
* @throws InvalidArgumentException for parameter/option parsing errors | ||
* @throws DriverRuntimeException for other driver errors (e.g. connection errors) | ||
*/ | ||
public function listDatabaseNames(array $options = []) |
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.
Just left a related comment about this on the Database::listCollectionNames
method. Perhaps it makes sense to only document that we return a Traversable or Iterator.
Return Values | ||
------------- | ||
|
||
A generator containing the name of each database on the server. |
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.
Since this hasn't been changed yet, please see my other comment about only documenting a Traversable or Iterator. There may not be any reason to inform users that we're using Generators internally.
802f8d4
to
5aac54c
Compare
https://jira.mongodb.org/browse/PHPLIB-547