@@ -74,7 +74,8 @@ public class ExportListener implements QueryBatchListener {
7474 private QueryManager .QueryView view ;
7575 private Set <DocumentManager .Metadata > categories = new HashSet <>();
7676 private Format nonDocumentFormat ;
77- private List <Consumer <DocumentRecord >> exportListeners = new ArrayList <>();
77+ private List <Consumer <DocumentRecord >> documentListeners = new ArrayList <>();
78+ private Consumer <DocumentPage > documentPageListener ;
7879 private boolean consistentSnapshot = false ;
7980 private List <BatchFailureListener <Batch <String >>> failureListeners = new ArrayList <>();
8081 private List <BatchFailureListener <QueryBatch >> queryBatchFailureListeners = new ArrayList <>();
@@ -127,15 +128,19 @@ public void initializeListener(QueryBatcher queryBatcher) {
127128 @ Override
128129 public void processEvent (QueryBatch batch ) {
129130 try ( DocumentPage docs = getDocs (batch ) ) {
130- while ( docs .hasNext () ) {
131- for ( Consumer <DocumentRecord > listener : exportListeners ) {
132- try {
133- listener .accept (docs .next ());
134- } catch (Throwable t ) {
135- logger .error ("Exception thrown by an onDocumentReady listener" , t );
136- }
137- }
138- }
131+ if (documentPageListener != null ) {
132+ documentPageListener .accept (docs );
133+ } else {
134+ while ( docs .hasNext () ) {
135+ for ( Consumer <DocumentRecord > listener : documentListeners ) {
136+ try {
137+ listener .accept (docs .next ());
138+ } catch (Throwable t ) {
139+ logger .error ("Exception thrown by an onDocumentReady listener" , t );
140+ }
141+ }
142+ }
143+ }
139144 } catch (Throwable t ) {
140145 for ( BatchFailureListener <Batch <String >> listener : failureListeners ) {
141146 try {
@@ -232,9 +237,7 @@ public ExportListener withTransform(ServerTransform transform) {
232237 * file system, a REST service, or any target supported by Java. If further
233238 * information is required about the document beyond what DocumentRecord can
234239 * provide, register a listener with {@link QueryBatcher#onUrisReady
235- * QueryBatcher.onUrisReady} instead. You do not need to call close() on
236- * each DocumentRecord because the ExportListener will call close for you on
237- * the entire DocumentPage.
240+ * QueryBatcher.onUrisReady} instead.
238241 *
239242 * @param listener the code which will process each document
240243 * @return this instance for method chaining
@@ -243,10 +246,32 @@ public ExportListener withTransform(ServerTransform transform) {
243246 * @see DocumentRecord
244247 */
245248 public ExportListener onDocumentReady (Consumer <DocumentRecord > listener ) {
246- exportListeners .add (listener );
247- return this ;
249+ if (this .documentPageListener != null ) {
250+ throw new IllegalStateException ("Cannot call onDocumentReady if a listener has already been set via onDocumentPageReady" );
251+ }
252+ documentListeners .add (listener );
253+ return this ;
248254 }
249255
256+ /**
257+ * Sets a listener to process a page of retrieved documents. Useful for when documents should be written to an
258+ * external system where it's more efficient to make batched writes to that system. Note that {@code close()} does
259+ * need to be invoked on the {@code DocumentPage}; this class will handle that.
260+ *
261+ * @param listener the code which will process each page of documents
262+ * @return this instance for method chaining
263+ * @see Consumer
264+ * @see DocumentPage
265+ * @since 6.2.0
266+ */
267+ public ExportListener onDocumentPageReady (Consumer <DocumentPage > listener ) {
268+ if (this .documentListeners != null && !this .documentListeners .isEmpty ()) {
269+ throw new IllegalStateException ("Cannot call onDocumentPageReady if a listener has already been added via onDocumentReady" );
270+ }
271+ this .documentPageListener = listener ;
272+ return this ;
273+ }
274+
250275 /**
251276 * When a batch fails or a callback throws an Exception, run this listener
252277 * code. Multiple listeners can be registered with this method.
0 commit comments