@agorrod , it's true we don't have to look this up (resetResults) each time, we could cache the method id - if we don't mind a static global var to stash it.  Same for notify's method id, it would speed this up.

As for why the async code looks different from the cursor code here.  Two reasons: one is that for cursor, we have results as soon as the API call (search/insert) completes.  For async, we have the results in notify().  Some background:  Java does all transfers using 'raw' mode and packs/unpacks within Java (I think that just makes the typing work better).  Consider Cursor.search() - the implementation does the unpack of key/value when the native WT cursor search call completes.  For AsyncOp.search(), we can't do an unpack at the time of AsyncOp.search(), for equivalent code, we would need to call unpack during notify().

The other difference (and the reason you don's see an unpack call in notify) is an optimization.  Rather than incurring the cost of unpacking both key and value up front (consider that the app may never call op.getKey() or op.getValue()), instead resetResults() invalidates the unpackers, and on the first call to op.getKey(), the key unpacking is done, and on first call to op.getValue(), the value unpacking is done.  The optimization also makes the notify code cleaner.  We don't have to unpack just value or both key/value depending on whether the op was search or insert or update: we just invalidate.

We could make the equivalent optimization to cursor.search().