OperationGroup extends AutoCloseable
Mark Rotteveel
mark at lawinegevaar.nl
Fri Jul 20 07:54:56 UTC 2018
I have to say I find these parts of ADBA a bit confusing, and I wonder
if these kind of rules don't make it too complex and prone to incorrect
use. Unfortunately, I still haven't had the time or energy to do a real
deep dive into all parts of ADBA, so I can't really offer an insightful
alternative yet.
For one, I don't really understand what an `OperationGroup` is supposed
to represent, and how it is different from just a `Connection` (ie: why
is it modeled separately), and why it should be 'submittable' at all. I
also don't understand why you can do more things to it after a
`submit()`, as submit sounds like a final operation to me. On the other
hand, as the code below demonstrates, not accepting new operations would
lead to usage errors. It sounds a bit like a transaction, but then
`Transaction` is modeled separately.
Unfortunately, the javadoc on `OperationGroup` doesn't help much in
understanding it.
Mark
On 2018-07-19 21:01, Douglas Surber wrote:
> Yes, all the calls are non-blocking. The close doesn’t “terminate the
> group”. It notifies the implementation that no more member Operations
> will be added. It doesn’t stop anything from executing.
>
> What I didn’t discuss but should have is the case where members are
> added as a result of the execution of other Operations.
>
> OperationGroup grp = session.operationGroup();
> grp.submit();
> grp.rowOperation(selectSql)
> .collect(Collector.of( () -> null,
> (n, c) ->
> grp.rowCountOperation(insertSql)
> .set(“param”,
> c.at <http://c.at/>(“index”).get(Integer.class), AdbaType.INTEGER)
> .submit(),
> (l, r) -> l,
> n -> { grp.close(); return n;}))
> .submit();
>
> The above does an insert for each row selected. The OperationGroup
> cannot be closed by try with resources because it would be closed
> before all (any) of the inserts are added. The problem with this
> pattern is failing to call grp.close() in the finalize method. If that
> happens the OperationGroup will never be completed and execution will
> hang.
>
> This was the code pattern that motivated the ability to add members
> after submit, but I don’t believe it will be the most common use case.
> It’s unfortunate that it doesn’t fail overtly rather than hanging, but
> the current design is no better in this regard. It just has more
> explicit method names. I don’t think those method names carry their
> weight compared to using try with resources.
>
> You can write exactly the code above with a RowPublisherOperation. It
> takes a few more lines of code to define the Subscriber, but it’s not
> hard.
>
> Douglas
>
>> On Jul 19, 2018, at 11:11 AM, Dávid Karnok <akarnokd at gmail.com> wrote:
>>
>> Aren't those submit calls (supposed) asynchronous? In that case, won't
>> the try-with-resources terminate the group before, most likely,
>> anything could even happen?
>>
>> The scenario sounds like typical multi-valued asynchronous flow, for
>> which a Flow.Publisher<Submission> source would be able to generate
>> more submissions as well as indicate there won't be any further
>> submissions.
>>
>> Douglas Surber <douglas.surber at oracle.com
>> <mailto:douglas.surber at oracle.com>> ezt írta (időpont: 2018. júl. 19.,
>> Cs, 19:46):
>> OperationGroup has a problem. It needs to be possible to add more
>> member Operations to an OperationGroup after it is submitted. It is
>> also necessary to know when all member Operations have been added as
>> the OperationGroup cannot be completed until it knows no more member
>> Operations will be added. Finally we want to minimize the likelyhood
>> of Session execution hanging because an OperationGroup is waiting for
>> more members when there are none.
>>
>> I approached this problem by specifying that by default no more member
>> Operations can be added after the OperationGroup is submitted. For the
>> case where members need to be added after submission there are two
>> special methods.
>>
>> public Submission<T> submitHoldingForMoreMembers();
>> public Submission<T> releaseProhibitingMoreMembers();
>>
>> The long, descriptive names are intentional. The goal is to clearly
>> remind users that they must release the OperationGroup if they hold
>> it. I’ve never liked this approach.
>>
>> I’d like to offer an alternative.
>>
>> - Remove submitHoldingForMoreMembers and
>> releaseProhibitingMoreMembers.
>> - Define OperationGroup to implement AutoCloseable.
>> - Member Operations can be added to an open OperationGroup.
>> - An OperationGroup will not be completed until after it is closed.
>> - An OperationGroup must be submitted before it is closed.
>>
>> try (OperationGroup grp = session.operationGroup()) {
>> grp.rowCountOperation(insertSql)
>> .submit();
>> CompletionStage result = grp.submit().getCompletionStage();
>> grp.rowCountOperation(updateSql)
>> .submit();
>> }
>>
>> A single usage pattern using try with resources seems much more
>> reliable that the multiple usage patters with unfamiliar methods. Yes,
>> the default case
>>
>> OperationGroup grp = session.operationGroup();
>> grp.rowCountOperation(insertSql)
>> .submit();
>> grp.rowCountOperation(updateSql)
>> .submit();
>> return grp.submit().getCompletionStage();
>>
>> is perhaps simpler, but not by much.
>>
>> try (OperationGroup grp = session.operationGroup()) {
>> grp.rowCountOperation(insertSql)
>> .submit();
>> grp.rowCountOperation(updateSql)
>> .submit();
>> return grp.submit().getCompletionStage();
>> }
>>
>> I’m starting to believe that the default case is not going to be the
>> most common case. I think held OperationGroup are going to be much
>> more common than I initially believed. A “held” group would look very
>> similar to the “default” case.
>>
>> try (OperationGroup grp = session.operationGroup()) {
>> CompletionStage result = grp.submit().getCompletionStage();
>> grp.rowCountOperation(insertSql)
>> .submit();
>> grp.rowCountOperation(updateSql)
>> .submit();
>> return result;
>> }
>>
>> The only difference is when the OperationGroup is submitted. If
>> OperationGroups are always written using try with resources the
>> forgetting to close one will be rare and easily noticed in code
>> reviews. The tiny advantage of the default case, not having to call
>> close, doesn’t seem to buy much compared to the complexity the current
>> model adds to the held case. Uniform use of try with resources seems a
>> much better approach.
>>
>> Thoughts?
>>
>> Douglas
>>
>>
>>
>>
>> --
>> Best regards,
>> David Karnok
More information about the jdbc-spec-discuss
mailing list