# PODNAME: Neo4j::Driver::TODO
# ABSTRACT: Information on planned improvements to Neo4j::Driver

=encoding utf8

=head1 TODO

=head2 Address open issues on GitHub

See L<https://github.com/johannessen/neo4j-driver-perl/issues>.

=head2 Functionality and API

=over

=item * Implement spatial and temporal types.

=item * Add timers to L<Neo4j::Driver::ResultSummary> (see C<Neo4j::Bolt>).

=back

=head2 Experimental features

=over

=item * L<Neo4j::Driver/"Parameter syntax conversion">: make stable and move
filter implementation to C<Transaction> in preparation of Bolt v3 support

=item * L<Neo4j::Driver::Session/"Calling in list context">: make illegal

=item * L<Neo4j::Driver::Transaction/"Calling in list context">: make illegal

=item * L<Neo4j::Driver::Transaction/"Execute multiple statements at once">:
This feature should no longer be exposed to the client. It complicates the API
significantly and is not that big of an optimisation anyway, because results
are typically fetched I<before> the next statement is run.

=item * L<Neo4j::Driver::Transaction/"Return results in graph format">,
L<Neo4j::Driver::Record/"graph">: make driver config option

=back

=head2 Tests, code quality, documentation

=over

=item * Test roundtrip of special numeric values
(very large integers, -0.0, ±Inf, ±NaN).

=item * Try to modify the way the data is stored to verify the tests fix in 0.13.
In particular, the URLs maybe should be parsed by the new type classes instead
of C<deep_bless>.

=item * Convert tests in C<xt/compatibility> to use L<Module::Load>, so that
testing/dev dependencies are fewer.

=item * Improve test coverage:

=over

=item * Many yet uncovered code paths are obviously fine, but difficult or
impossible to cover. In some of these cases, it may be possible to refactor the
code, such as by banking on autovivification (i.e. don't defend against undefined
C<$a> in expressions like C<< $a->{b} >>; see L<perlref/"Using References">).

=item * The C<deep_bless> subs contain a lot of assertions and other checks
that are not normally necessary. Since this logic seems to work fine, it should
be simplified. (This may also make it easier to unroll the recursion later.)

=item * The current policy of not documenting deprecated methods is informed by
the principle to "design interfaces that are: consistent; easy to use correctly;
hard to use incorrectly". Perhaps simply listing the deprecated method names
with short note like "deprecated in 0.13" would be an acceptable addition that
also fulfils the B<pod> coverage requirements.

=item * Documenting each attribute in L<Neo4j::Driver::SummaryCounters> as individual
methods might be a quick way to bring up the B<pod> coverage stats a bit.

=item * Making sure all private methods (e. g. in Neo4j::Driver::Transport::*)
have names beginning with C<_> might help to improve B<pod> coverage.

=back

=item * List possible C<croak> output in L<Neo4j::Driver/"DIAGNOSTICS">,
allowing for indexing by search engines.

=item * L<Neo4j::Driver::ResultSummary/"notifications">: clarify docs on list context

=item * Optimise the simulator for C<$hash = 0>.
Use of C<<< << >>> causes statements to end with C<\n>, which the simulator
could filter out. 
The internals test "transaction: REST 404 error handling" should run a distinct
statement.

=item * Try to change "no connection" tests such that no C<NXDOMAIN> responses
are required by (ab)using a particular port number on localhost; the port could
be checked beforehand and the test skipped if it happens to be open for some
reason. Alternatively, the tests in question could be changed to a simulated
connection failure.

=back

=head1 Other ideas for specific modules

=head2 L<Neo4j::Driver>

=over

=item * Make the URL a config option, so that it can be queried (and changed).

=item * Make the auth data a config option, so that it can be queried. As
alternative ways to I<set> the auth data, C<basic_auth()> should continue
to be supported as an alias and the user info should be parsed from the URL
if given (however, URLs without user info should not change the auth data
stored in the driver). A possible implementation would be to create a new
L<AuthToken|https://neo4j.com/docs/api/java-driver/current/index.html?org/neo4j/driver/AuthTokens.html>
module that would offer suitable methods, but this seems like overkill.

=item * Allow passing config options directly to the constructor, e. g. in
place of the URL (C<< Neo4j::Driver->new({ url=>"bolt:", timeout=>30 }) >>).

=item * Consider writing a concrete example that re-creates LOMS logic by
re-blessing the structural types into custom types from the business logic
using C<< $cypher_types->{init} >>. (For example, check for Neo4j nodes that
are labelled C<:Person> and re-bless those as C<Local::Person> or whatever.)

=back

=head2 L<Neo4j::Driver::Session>

=over

=item * Sessions of some of the official drivers can have at most one
transaction running at a time. This restriction is not necessary for this Perl
driver when HTTP is used, but perhaps we should implement it anyway for
consistency.

=item * L<DBI> uses C<begin_work> in place of C<begin_transaction> as a method
name. Even though C<begin_work> is shorter, it should not be the main method
name because C<begin_transaction> is well established in the official Neo4j
drivers, and after all this is I<not> C<DBI>. However, as this is the only
(almost) exact equivalence with C<DBI> that we have, we should perhaps offer
C<begin_work> as an experimental alias at least.

=item * Consider whether to offer
L<transaction functions|https://neo4j.com/docs/driver-manual/current/session-api/simple/#driver-simple-transaction-fn>.
If available, these should consist of subrefs passed to methods called
C<write_transaction> and C<read_transaction>. These access modes are only an
optimisation for Enterprise features. We don't target those at present, but
C<read_transaction> could then eventually be routed to a high-performance
read-only server once clusters are supported. It would make sense to offer
both methods right away even though initially they'd work exactly the same.

=back

=head2 L<Neo4j::Driver::Transaction>

=over

=item * Consider supporting re-using C<Record> objects for query parameters in
C<run>. The Java and C# drivers do this.

=item * Run statements lazily: Just like with the official drivers, statements
passed to C<run> should be gathered until their results are actually accessed.
Then, and only then, all statements gathered so far should be sent to the
server using a single request. Challenges of this approach include that
notifications are not associated with a single statement, so there must be an
option to disable this behaviour; indeed, disabled should probably be the
default when stats are requested. Additionally, there are some bugs with
multiple statements (see tests C<non-arrayref individual statement> and
C<include empty statement>). Since stats are now requested by default,
this item might mean investing time in developing an optimisation
feature that is almost never used. Since the server is often run on localhost
anyway where latency is very close to zero, this item should not have high
priority.

=back

=head2 L<Neo4j::Driver::StatementResult>

=over

=item * Rename C<Result>, in line with the official drivers.

=item * Perhaps C<fetch()> should always buffer two records instead of just
one. With the current implementation, the bolt connection might remain
attached longer than desirable in cases where the client knows in advance
how many records there will be and calls C<fetch()> exactly that number of
times. (Such a change might even slightly improve performance if the driver
successfully uses Perl threads to fill the buffer in the background.)

=back

=head2 L<Neo4j::Driver::Record>

=over

=item * Consider whether to implement methods to query the list of fields for
this record (C<keys>, C<has>, C<size>) and/or a mapping function for all fields
(C<map>/C<forEach>). Given that this data should easily be available through
the StatementResult object, these seem slightly superfluous though.

=item * Implement C<graph>; see
L<https://github.com/neo4j/neo4j/blob/3.5/community/server/src/main/java/org/neo4j/server/rest/transactional/GraphExtractionWriter.java>,
L<https://github.com/neo4j/neo4j-python-driver/wiki/1.6-changelog#160a1>.

=back

=head2 L<Neo4j::Driver::ResultColumns>

=over

=item * The entire package can probably be removed now.

=back

=head2 L<Neo4j::Driver::ResultSummary>

=over

=item * Profile the server-side performance penalty of requesting stats for
various kinds of queries. If the penalty turns out to be high, stats should
perhaps have to be requested explicitly by clients (rather than being
obtained by default, as with 0.13 and higher). However, using Bolt always
provides stats, and different APIs for HTTP and Bolt seem like a bad idea.

=back

=head2 L<Neo4j::Driver::SummaryCounters>

=over

=item * C<use Class::Accessor::Fast 0.34;>

=back

=head2 L<Neo4j::Driver::Transport::HTTP>

=over

=item * Profile whether X-Stream has any performance impact. Remove if
in doubt, as we don't implement streaming (and have no plans to in the
future, considering that Bolt should be used when speed is important).

=item * Consider unrolling C<deep_bless> recursion. Based on initial profiling,
this may save up to about 5% CPU time (for a specific HTTP test query cached in
RAM, performance went from about 2700/s to 2850/s when skipping the call to
C<deep_bless> entirely). However, when accessing the database, the bottleneck
is typically I/O (querying Neo4j itself instead of the RAM-cached response let
the performance for the very same query drop down to 650/s when executed over
HTTP). So this optimisation may not be worth it (OTOH, Bolt performance was
something like 7000/s, so optimising C<deep_bless> may be more useful there).

=item * Consider making the JSON module configurable. For example, clients
might wish to use L<Mojo::JSON> instead of L<JSON::MaybeXS>; it also prefers
L<Cpanel::JSON::XS> where available, but in Pure Perl it may be faster than
L<JSON::PP>. Also, there is L<JSON::Tiny>.

=back

=head2 Neo4j::Driver::Type::*

=over

=item * The C<eq> and C<ne> operators should be overloaded to allow
for ID comparison on nodes and relationships.

=item * Consider whether to use C<use overload '%{}'> to allow direct
access to e. g. properties using the pre-0.13 hashref syntax. See
L<https://metacpan.org/pod/overload#Two-face-References> for an example.
L<perltie> might perhaps also work.

=item * Try to refactor L<Neo4j::Driver::Type::Path>'s internal representation
to allow either elements or nodes+rels. Have one autogenerate from the other,
then cache the results. May not actually have advantages for deep_bless though.

=back
