# SDLIP-Asynch

SDLIP document map and recommended reading sequence (click to navigate):

Contents:

1. Introduction and Overview
2. SDLIP-Asynch Operations in Detail
2.1 The Asynchronous Search Interface
2.2 The Delivery Interface
2.3 The Asynchronous Result Access Interface

## 1. Introduction and Overview

This document describes an extension to SDLIP-Core. Servers that support this optional extension can interact with clients asynchronously. This is important, for example, if a service performes long-lasting, or even continuous searches. For example, a client might submit a query to such a service and request that the query be repeatedly performed over a changing collection, such as financial news. Results are to be delivered to the client as they become available. Rather than having to poll the server repeatedly, clients can rely on the server to deliver the results.

Figure 1 shows how three new interfaces are added to SDLIP-Core to manage this scenario:

Figure 1: SDLIP-Asynch adds asynchronous search, asynchronous result access, and delivery interfaces to SDLIP-Core

Asynchronous searches are submitted to the server through the new asynchronous search interface. The service transfers the results to the client, using the new, client-side delivery interface. Similarly, asynchronous result set follow-on requests may be delivered through the new asynch result access interface.

Clients may discover whether a service supports the asynchronous interface by using the `getInterface()` source metadata operation described in SDLIP-Core.

Figure 2 shows a variety of scenarious that can be constructed with the SDLIP-Asynch extension.

Figure 2a: Asynchronous requests for search, and follow-up information
Figure 2b: Asynchronous operation. Separate cache in client application's address space implements delivery interface
Figure 2c: Client asynchronously accesses asynchronously constructed cache in a third address space
Figure 2d: Server delegates delivery (network boundaries are omitted for clarity)
Figure 2: Different Configurations for Using SDLIP

Figure 2a illustrates asynchronous operation by including the delivery interface on the client. The client requests the search (1). The service uses the delivery interface to return the results one by one as they become available, or in batches (2). The client may ask for more documents, or additional portions of documents already submitted (3). The client's delivery interface is again used to move the information to the client (4). The drawback of this configuration is that every client application now needs to carry the responsibility of implementing the delivery interface.

To get around this problem, Figure 2b adds a 'result cache' object on the same machine as the client application (as indicated by the dotted network partition arc). The client application creates this object, and then submits the asynchronous search request to the service (1). As part of this request, the client informs the service of where to find the object that implements the delivery interface. The client application can now continue to operate, while the result cache object faithfully awaits arrival of the results. Once the results have arrived (2), the client application uses the result access interface to pull them out of the result cache one by one (3). In Figure 2b, the result access interface is invoked synchronously. If the client should be able to ask its local result cache for portions of the result that were not requested as part of the search, then the LSP in Figure 2b would also need a result access interface. The cache would then forward requests for locally unavailable portions of the result to the LSP.

Figure 2c is a variation of Figure 2b in that the result cache is created on a machine other than the one running the client application. This configuration is useful for thin clients interacting with services that do not maintain state at all, or only for short periods of time. In order to make due with little client-side memory, the result cache can receive results on the client's behalf, and can store them until the client extracts, uses, and discards one document (or even document portion) at a time. Apart from decreased memory requirements for the client, this configuration saves the day when the connection between client and service is frequently interrupted, as might be the case with mobile clients connected through wireless networks. In such a scenario, the mobile client might be out of touch for several days. In the configuration of Figure 2b, the service might make some failed connection attempts to deliver results. It would then eventually discard the session state, leaving the client disappointed, once it is finally back on the network. If the result cache is placed at a stationary point that is well connected with the service, the results are safe and accessible once the client returns to the network.

Figure 2d, finally, illustrates how services can delegate interactions with clients if the service object gets overloaded (2), yet wishes to maintain state for the client. This is very similar to the analogous case in SDLIP-Core. As part of the delivery interface, servers can specify a future contact address (3). All future deliveries are made by the delegate. If the client wishes, for example, to recall more documents of the result set than it asked for in its initial search request, then it will use the delegate's address, rather than the main address (4).

## 2. SDLIP Operations in Detail

We describe each of the new interfaces in turn. For each interface, we list the associated operations, and explanations for each parameter, although parameters that have analogies in SDLIP-Core are often not explained again in this document.. Parameter conventions and notation is just as in the SDLIP-Core specification.

### 2.1 The Aynchronous Search Interface

Figure 3 gives an overview of the asynchronous search process.

Figure 3: The Asynchronous Search Process

The `searchAsynch()` method allows clients to transmit a query to a target library service proxy (LSP).

    Void searchAsynch(            // Submit query. Result to be delivered by
                                  // calls to the deliveryTarget.
      Long clientSID,             // {0} Client-side session ID (unique within client)
      XMLObject subcols,          // {service's default (or sole) subcollection}
                                  // Collections or previous results to search w/in LSP
      XMLObject query,            // The query
      Long numDocs,               // {-1}Number of documents to return (-1: all)
      XMLObject docProps,         // {all possible properties} Properties to return for
                                  // each result doc (e.g. <propList><Abstract/><Title/>, ...)
      Long stateTimeoutReq,       // {0}Request for number of seconds to
                                  // maintain state at server. -1: request unlimited time
      XMLObject queryOptions,     // {null} Additional info for the LSP
      Delivery retTarget          // Address of the entity that implements a delivery interface
    )

The `retTarget` is the address to which the LSP is to deliver results. For a distributed object implementation this would be an object that implements the delivery interface. For an HTTP-based transport binding, it would be the URL. For a client site this means that some entity must be up and running which implements the delivery interface described below. When results are available, the LSP will invoke `addDocs()` operations on that entity's delivery interface. When using CORBA, this entity will be a CORBA object. When using an HTTP based transport, it will be a server listening on the port that is advertised as part of the `retTarget` URL.

If the client has submitted a `searchAsynch()` request, and wishes to abort the search:

    Void cancelRequest(
      Long serverSID,       // {0}
    )

### 2.2 The Delivery Interface

The delivery interface allows library service proxies to deliver documents to the client asynchronously. The scenario is that the client has issued a `searchAsynch()` request to the LSP at some earlier time. The LSP has been processing the request. Now at least some of the results are available. The LSP uses the delivery interface to return the requested documents (or document pieces) to the client. They are either delivered all in one bunch, or piece by piece as the LSP can pull the information out of the underlying information repository.

Once the LSP has completed at least some of the search, and is ready to deliver some of the result documents, it invokes the `setSessionInfo()` operation on the client. The `setSessionInfo()` call lets the client know how many results are (at least expected to be) available at the LSP. Note: this is not the number of documents already delivered to the client. It is the size of the result set.

    Void setSessionInfo(    // Expected total number of deliverable docs
                            // in response to a searchAsynch().
      Long clientSID,       // {0}
      Long serverSID,       // {0} ID used at server to identify this session
      Long ResultAccess serverDelegate, // {same as for original query}
                            // Server-side delegate to use for this session.
      Long expectedTotal,   // {0} If -1: number is unknownable. If -2: number not yet known
      Long stateTimeout     // {0}
    )

The `serverSID` is the session ID the server uses to identify this session. All correspondence with the server regarding this session must include that ID. The `serverDelegate` is the same as the parameter of the same name in SDLIP-Core's `search()`: an address for the client to use for follow-up information regarding this session. If NULL, there is no change in address.

Sometimes, the total number of results cannot be determined by the LSP. For example, if an LSP continuously serves out a stream of documents matching a 'standing' query, and the underlying source is constantly being added to, then setting the total number of documents does not make sense. In this case, `expectedTotal` is set to -1.Occasionally, LSPs will eventually know the total number of documents, but they wish to give the client a chance to begin accessing documents in the partially filled result set. In that case, `expectedTotal` is set to -2. Clients can use the `getSessionInfo()` operation (see below) to learn about the result set size later.

The `stateTimeout` parameter is the number of seconds the server is willing to maintain state.

The `addDocs()` method is the most important operation of the delivery interface. It transfers the documents from the service to the client.

    Void addDocs(                 // Add results to a client-side Delivery entity
      Long clientSID,             // {0} The client-side session ID
      Long reqID,                 // {0} 0 if this call was triggered by the
                                  // original call to searchAsynch(). Else see
                                  // getDocsAsynch() for an explanation of
                                  // this parameter
      XMLObjct result             // XML list of results
    )

The `clientSID` is the same that was passed in the original `searchAsynch()` call. It helps the client keep track of why these results are being delivered. There is also a `reqID`. This is zero if the results are the reponse to an initial `searchAsynch()`. If they are the result of a previous `getDocsAsynch()` call, then the request ID provided by the client as part of that call will be returned in this parameter.

The `result` parameter, finally, is the meat: it is the XML-encoded list of result documents. Format is the same is in SDLIP-Core.

The `raiseException()` method on the delivery interface is used when something went wrong with an asynchronous search or document retrieval request.

    Void raiseException(
      Long clientSID,                // {0}
      Long reqID,                    // {0}
      XMLObject errDesc              // XML-Encoded information on the reasons for the failure
    )

The `errDesc` is the XML-encoded list of reasons for the failure. Note that if the delivery interface is implemented by a result cache (as in Figure 2c), then the exception will make it back to the client only when the client attempts the next result access through the result access interface.

### 2.3 The Asychronous Result Access Interface

Once some of the documents have been returned, clients might want to get more documents than they had originally requested, or they might need to request additional properties of documents they already have. This is accomplished through the result access interface. Figure 4 gives an overview of the process.

Figure 4: Asynchronous Access to Result Sets Maintained at the Server Site

The `getDocsAsynch()` operation is the cousin of SDLIP-Core's `getDocs(.)`It is the means by which clients ask for more documents, or for additional portions of partially transfered documents in a result set. The key notion is that client and server think of the result documents as being arranged in order within a result array. Documents are referenced by their zero-based index into that array.

    Void getDocsAsynch(   // Used to get more docs in existing session
      Long serverSID,       // {0} ... of the original query
      Long reqID,           // {0} new for each call
      XMLObject docProps,   // {all possible properties} properties to get
      String docsToGet,     // {1-} Doc indexes to get. Ex: "1,2,5-11". "1-" :all
      Delivery retTarget    // Address of entity that implements the delivery interface.
    )

When the originally agreed upon time limit for result state maintenance is about to expire, the client needs to call
`extendStateTimeout()`, if the client still wishes to access that state.

    Void extendStateTimeout(// Request more time for server to
      Long serverSID,       // {0} maintain search result state.
      Long additionalTime,
      OUT Long timeAllotted // Num of secs server agrees to maintain state
    )

The LSP returns the amount of additional time it is actually willing to maintain the state for the client.

Alternatively, sometimes, a client may want to release server state prematurely, or it may have changed its mind about a request it delivered earlier. It can use `cancelRequest()` for these situations:

    Void cancelRequest(
      Long serverSID,               // {0}
      Long reqID                    // {0}
    )

The `reqID` is 0 if all outstanding requests for this session are to be canceled. This has the semantics of closing the session, and allowing the server to free its resources. If `reqID` is not zero, only the corresponding request within the session is canceled.

The `getSessionInfo()`allows clients to find out about the result set. This operation is useful mostly if the LSP's earlier invocation of the `setSessionInfo()` did not yet have all the information, such as total size of the result set.

    Void getSessionInfo()
      Long serverSID,                        // {0}
      OUT Long expectedTotal,// {0} -1 if unknowable. -2 if not yet known.
      OUT Long stateTimeout  // {0} Total number of seconds server is willing to
                             // hold state. -1 if forever.
    )