Hi Christopher,

I did not forget this thread :-)
However, I want to clear the other topics first, before going into
this one. This one still needs some thinking on my side.

Cheers
Lukas

2013/3/30 Christopher Deckers <[email protected]>:
> Hi Lukas,
>
> OK, here is the API challenge of the day.
> This is to sum up my views on Executor and Configuration and hopefully also
> make users of the library react! :)
>
> I believe there are several cases for Executor creation:
> - Create an Executor with ad-hoc parameters.
> - Create an Executor with a Configuration.
> - And eventually: create an Executor with a Configuration, overridden with
> ad-hoc parameters.
>
> I am mainly focusing on the 2nd/3rd cases: creating an Executor with a
> Configuration.
>
> When someone uses a Configuration, I believe that the purpose is to not
> repeat parameters, to have the same parameters for all Executors. In some
> cases, which I think are limited, someone could have more than one
> Configuration, but would still use those as shared parameters for sets of
> Executors. The purpose of this e-mail is to suggest strengthening this
> notion of Configuration as a global shareable set of parameters.
>
>
> In my view, because a Configuration shares parameters, it should by nature
> not share object instances that have a state that depends on execution.
> Otherwise, 2 calls from different threads could fail if they happen at the
> same time; 2 sequencial queries where the first one lazily fetches the
> results could also fail.
> The best a Configuration should do in this area is to provide a factory of
> such execution-dependant objects. Actual instances should be set on the
> Executor directly.
>
> The main objects that may have a state which depends on execution currently
> are:
> - ExecuteListener: an actual instance is plugged to the Configuration
> object. Storing state directly in that class is very dangerous and the
> workaround is to use the data map of the ExecuteContext to store and
> retrieve execution-related state. Failing to do so may work until 2 threads
> call it at the same time, etc.
> - ConnectionProvider: the specification is very loose on how to implement
> it, which means that the same connection could be acquired by 2 threads
> using the same configuration.
>
> Because of the current structure of the API, it is easy to misuse and to
> share a configuration object which eventually shares stateful execute
> listeners and connections (through connection providers). It would
> eventually blow up randomly depending on threading or query execution flows
> (preferably once deployed in production) and would of course be very hard to
> debug.
>
>
> I think ExecuteListener and ConnectionProvider should be replaced so that
> the user can:
> - Set an actual instance of X (see below) on an Executor instance.
> - Set a factory of X in the Configuration, which can be used by many
> Executor instances.
>
>
> About ExecuteListener, the user could either:
>
> 1. Define an ad-hoc ExecuteListener instance:
> Executor executor = new Executor(configuration);
> executor.getExecuteListeners().add(new MyExecuteListener());
>
> 2. Define a global ExecuteListener factory:
> configuration = new Configuration();
> configuration.getExecuteListenerFactories().add(new ExecuteListenerFactory()
> {
>   public ExecuteListener createExecuteListener() {
>     return new MyExecuteListener();
>   }
> });
> // Everywhere the configuration is used, then:
> Executor executor = new Executor(configuration);
>
> A few notes:
> - If per-execution state is needed, the factory would just create a new
> instance, which is the general case. Of course, the factory can supply the
> same instance of the ExecuteListener if it wishes so, but then it is not a
> factory anymore and as such the implementor will have to create its
> ExecuteListener subclass with thread safety in mind. Such cases are for
> example for aggregation of statistics over multiple queries and threads, and
> is by nature required to be coded in a thread safe way.
> - If using a factory seems like clutter, keep in mind that the configuration
> is to define shared parameters and is not done at many places in the code.
> Moreover, with Lambda in Java 8 this turns into a one liner.
>
>
> About the ConnectionProvider, the user could either:
>
> 1. Define an ad-hoc connection instance:
> Executor executor = new Executor(conn, sqlDialect);
>
> 2. Define a global factory:
> configuration = new Configuration();
> configuration.setConnectionProvider(new MyPoolBasedConnectionProvider());
> // Everywhere the configuration is used, then:
> Executor executor = new Executor(configuration);
>
> A few notes:
> - The ConnectionProvider would not be loose in its meaning as it is
> currently and it would specify that every connection that is obtained
> through acquire() cannot be returned twice until it is returned with
> release(conn). This way, the connection provider can be used by concurrent
> queries.
> - A side effect, but not the main motivation, is that the ConnectionProvider
> would be a safe place to acquire/release dedicated connections. 3rd party
> ExecuteListener or whatever tools could make use of such capability.
> - Maybe we should also have signatures like: "new Executor(Configuration,
> conn)". The general idea would be that the configuration is used, but the
> executor can override some aspects of it like what I did with the
> ExecuteListener above. In fact, maybe we should have an API so that user can
> call "new Executor(Configuration)" and then call
> "executor.setConnection(conn)" if so they wish.
> - Because there is this idea that the Configuration is shared, when an
> Executor is instanciated it would create an internal copy to merge
> overridden aspects (connection, execute listeners, even rendering
> capabilities that could be accessed through executor.getConfiguration()).
>
>
> I strongly believe that it would make the API easier to understand (global
> vs ad-hoc) and would reduce the chances of misusing it. Please let me know
> if my thoughts are completely off-track or if such API would be beneficial
> to jOOQ.
>
> -Christopher
>
> --
> You received this message because you are subscribed to the Google Groups
> "jOOQ User Group" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

-- 
You received this message because you are subscribed to the Google Groups "jOOQ 
User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to