What are Operations



Why use operations

  • Operations provide management functionality that is Not available in the context of the session, for example:

    • Create/delete a database
    • Execute administrative tasks
    • Assign permissions
    • Change server configuration, and more.
  • The operations are executed on the DocumentStore and are Not part of the session transaction.

  • There are some client tasks, such as patching documents, that can be carried out either via the Session (session.Advanced.Patch()) or via an Operation on the DocumentStore (PatchOperation).

How operations work

  • Sending the request:
    Each Operation is an encapsulation of a RavenCommand.
    The RavenCommand creates the HTTP request message to be sent to the relevant server endpoint.
    The DocumentStore OperationExecutor sends the request and processes the results.
  • Target node:
    By default, the operation will be executed on the server node that is defined by the client configuration.
    However, server-maintenance operations can be executed on a specific node by using the ForNode method.
  • Target database:
    By default, operations work on the default database defined in the DocumentStore.
    However, common operations & maintenance operations can operate on a different database by using the ForDatabase method.
  • Transaction scope:
    Operations execute as a single-node transaction.
    If needed, data will then replicate to the other nodes in the database-group.
  • Background operations:
    Some operations may take a long time to complete and can be awaited for completion.
    Learn more below.

Common operations

  • All common operations implement the IOperation interface.
    The operation is executed within the database scope.
    Use ForDatabase to operate on a specific database other than the default defined in the store.

  • These operations include set-based operations such as PatchOperation, CounterBatchOperation,
    document-extensions related operations such as getting/putting an attachment, and more.
    See all available operations below.

  • To execute a common operation request,
    use the Send method on the Operations property in the DocumentStore.

Example:

// Define operation, e.g. get all counters info for a document
IOperation<CountersDetail> getCountersOp = new GetCountersOperation("products/1-A");

// Execute the operation by passing the operation to Operations.Send
CountersDetail allCountersResult = documentStore.Operations.Send(getCountersOp);

// Access the operation result
int numberOfCounters = allCountersResult.Counters.Count;
// Define operation, e.g. get all counters info for a document
IOperation<CountersDetail> getCountersOp = new GetCountersOperation("products/1-A");
    
// Execute the operation by passing the operation to Operations.Send
CountersDetail allCountersResult = await documentStore.Operations.SendAsync(getCountersOp);

// Access the operation result
int numberOfCounters = allCountersResult.Counters.Count;
Syntax:

// Available overloads:
void Send(IOperation operation, SessionInfo sessionInfo = null);
TResult Send<TResult>(IOperation<TResult> operation, SessionInfo sessionInfo = null);
Operation Send(IOperation<OperationIdResult> operation, SessionInfo sessionInfo = null);

PatchStatus Send(PatchOperation operation);
PatchOperation.Result<TEntity> Send<TEntity>(PatchOperation<TEntity> operation);
// Available overloads:
Task SendAsync(IOperation operation,
    CancellationToken token = default(CancellationToken), SessionInfo sessionInfo = null);
Task<TResult> SendAsync<TResult>(IOperation<TResult> operation,
    CancellationToken token = default(CancellationToken), SessionInfo sessionInfo = null);
Task<Operation> SendAsync(IOperation<OperationIdResult> operation,
    CancellationToken token = default(CancellationToken), SessionInfo sessionInfo = null);

Task<PatchStatus> SendAsync(PatchOperation operation,
    CancellationToken token = default(CancellationToken));
Task<PatchOperation.Result<TEntity>> SendAsync<TEntity>(PatchOperation<TEntity> operation,
    CancellationToken token = default(CancellationToken));

The following common operations are available:


Maintenance operations

  • All maintenance operations implement the IMaintenanceOperation interface.
    The operation is executed within the database scope.
    Use ForDatabase to operate on a specific database other than the default defined in the store.

  • These operations include database management operations such as setting client configuration,
    managing indexes & ongoing-tasks operations, getting stats, and more.
    See all available maintenance operations below.

  • To execute a maintenance operation request,
    use the Send method on the Maintenance property in the DocumentStore.

Example:

// Define operation, e.g. stop an index 
IMaintenanceOperation stopIndexOp = new StopIndexOperation("Orders/ByCompany");
    
// Execute the operation by passing the operation to Maintenance.Send
documentStore.Maintenance.Send(stopIndexOp);

// This specific operation returns void
// You can send another operation to verify the index running status
IMaintenanceOperation<IndexStats> indexStatsOp = new GetIndexStatisticsOperation("Orders/ByCompany");
IndexStats indexStats =  documentStore.Maintenance.Send(indexStatsOp);
IndexRunningStatus status = indexStats.Status; // will be "Paused"
// Define operation, e.g. stop an index 
IMaintenanceOperation stopIndexOp = new StopIndexOperation("Orders/ByCompany");

// Execute the operation by passing the operation to Maintenance.Send
await documentStore.Maintenance.SendAsync(stopIndexOp);

// This specific operation returns void
// You can send another operation to verify the index running status
IMaintenanceOperation<IndexStats> indexStatsOp = new GetIndexStatisticsOperation("Orders/ByCompany");
IndexStats indexStats =  await documentStore.Maintenance.SendAsync(indexStatsOp);
IndexRunningStatus status = indexStats.Status; // will be "Paused"
Syntax:

// Available overloads:
void Send(IMaintenanceOperation operation);
TResult Send<TResult>(IMaintenanceOperation<TResult> operation);
Operation Send(IMaintenanceOperation<OperationIdResult> operation);
// Available overloads:
Task SendAsync(IMaintenanceOperation operation,
    CancellationToken token = default(CancellationToken));
Task<TResult> SendAsync<TResult>(IMaintenanceOperation<TResult> operation,
    CancellationToken token = default(CancellationToken));
Task<Operation> SendAsync(IMaintenanceOperation<OperationIdResult> operation,
    CancellationToken token = default(CancellationToken));

The following maintenance operations are available:


Server-maintenance operations

  • All server-maintenance operations implement the IServerOperation interface.
    The operation is executed within the server scope.
    Use ForNode to operate on a specific node other than the default defined in the client configuration.

  • These operations include server management and configuration operations.
    See all available operations below.

  • To execute a server-maintenance operation request,
    use the Send method on the Maintenance.Server property in the DocumentStore.

Example:

// Define operation, e.g. get the server build number
IServerOperation<BuildNumber> getBuildNumberOp = new GetBuildNumberOperation();
    
// Execute the operation by passing the operation to Maintenance.Server.Send
BuildNumber buildNumberResult = documentStore.Maintenance.Server.Send(getBuildNumberOp);

// Access the operation result
int version = buildNumberResult.BuildVersion;
// Define operation, e.g. get the server build number
IServerOperation<BuildNumber> getBuildNumberOp = new GetBuildNumberOperation();
    
// Execute the operation by passing the operation to Maintenance.Server.Send
BuildNumber buildNumberResult = await documentStore.Maintenance.Server.SendAsync(getBuildNumberOp);

// Access the operation result
int version = buildNumberResult.BuildVersion;
Syntax:

// Available overloads:
void Send(IServerOperation operation);
TResult Send<TResult>(IServerOperation<TResult> operation);
Operation Send(IServerOperation<OperationIdResult> operation);
// Available overloads:
Task SendAsync(IServerOperation operation,
    CancellationToken token = default(CancellationToken));
Task<TResult> SendAsync<TResult>(IServerOperation<TResult> operation,
    CancellationToken token = default(CancellationToken));
Task<Operation> SendAsync(IServerOperation<OperationIdResult> operation,
    CancellationToken token = default(CancellationToken));

The following server-maintenance operations are available:


Manage lengthy operations

  • Some operations that run in the server background may take a long time to complete.

  • For Operations that implement an interface with type OperationIdResult,
    executing the operation via the Send method will return an Operation object,
    which can be awaited for completion or aborted (killed).


Wait for completion:

public void WaitForCompletionWithTimout(
    TimeSpan timeout,
    DocumentStore documentStore)
{
    // Define operation, e.g. delete all discontinued products 
    // Note: This operation implements interface: 'IOperation<OperationIdResult>'
    IOperation<OperationIdResult> deleteByQueryOp =
        new DeleteByQueryOperation("from Products where Discontinued = true");
        
    // Execute the operation
    // Send returns an 'Operation' object that can be awaited on
    Operation operation = documentStore.Operations.Send(deleteByQueryOp);
    
    try
    {
        // Call method 'WaitForCompletion' to wait for the operation to complete.
        // If a timeout is specified, the method will only wait for the specified time frame.
        BulkOperationResult result =
            (BulkOperationResult)operation.WaitForCompletion(timeout);
        
        // The operation has finished within the specified timeframe
        long numberOfItemsDeleted = result.Total; // Access the operation result
    }
    catch (TimeoutException e)
    {
        // The operation did Not finish within the specified timeframe
    }
}
public async Task WaitForCompletionWithTimoutAsync(
    TimeSpan timeout,
    DocumentStore documentStore)
{
    // Define operation, e.g. delete all discontinued products 
    // Note: This operation implements interface: 'IOperation<OperationIdResult>'
    IOperation<OperationIdResult> deleteByQueryOp =
        new DeleteByQueryOperation("from Products where Discontinued = true");
        
    // Execute the operation
    // SendAsync returns an 'Operation' object that can be awaited on
    Operation operation = await documentStore.Operations.SendAsync(deleteByQueryOp);
    
    try
    {
        // Call method 'WaitForCompletionAsync' to wait for the operation to complete.
        // If a timeout is specified, the method will only wait for the specified time frame.
        BulkOperationResult result = 
            await operation.WaitForCompletionAsync(timeout)
                .ConfigureAwait(false) as BulkOperationResult;
        
        // The operation has finished within the specified timeframe
        long numberOfItemsDeleted = result.Total; // Access the operation result
    }
    catch (TimeoutException e)
    {
        // The operation did Not finish within the specified timeframe
    }
}
public void WaitForCompletionWithCancellationToken(
    CancellationToken token,
    DocumentStore documentStore)
{
    // Define operation, e.g. delete all discontinued products 
    // Note: This operation implements interface: 'IOperation<OperationIdResult>'
    IOperation<OperationIdResult> deleteByQueryOp =
        new DeleteByQueryOperation("from Products where Discontinued = true");
            
    // Execute the operation
    // Send returns an 'Operation' object that can be awaited on
    Operation operation = documentStore.Operations.Send(deleteByQueryOp);
    
    try
    {
        // Call method 'WaitForCompletion' to wait for the operation to complete.
        // Pass a CancellationToken in order to stop waiting upon a cancellation request.
        BulkOperationResult result =
            (BulkOperationResult)operation.WaitForCompletion(token);
        
        // The operation has finished, no cancellation request was made
        long numberOfItemsDeleted = result.Total; // Access the operation result
    }
    catch (TimeoutException e)
    {
        // The operation did Not finish at cancellation time
    }
}
public async Task WaitForCompletionWithCancellationTokenAsync(
    CancellationToken token,
    DocumentStore documentStore)
{
    // Define operation, e.g. delete all discontinued products 
    // Note: This operation implements interface: 'IOperation<OperationIdResult>'
    IOperation<OperationIdResult> deleteByQueryOp =
        new DeleteByQueryOperation("from Products where Discontinued = true");
            
    // Execute the operation
    // SendAsync returns an 'Operation' object that can be awaited on
    Operation operation = await documentStore.Operations.SendAsync(deleteByQueryOp);
    
    try
    {
        // Call method 'WaitForCompletionAsync' to wait for the operation to complete.
        // Pass a CancellationToken in order to stop waiting upon a cancellation request.
        BulkOperationResult result = 
            await operation.WaitForCompletionAsync(token)
                .ConfigureAwait(false) as BulkOperationResult;
        
        // The operation has finished, no cancellation request was made
        long numberOfItemsDeleted = result.Total; // Access the operation result
    }
    catch (TimeoutException e)
    {
        // The operation did Not finish at cancellation time
    }
}
Syntax:

// Available overloads:
public IOperationResult WaitForCompletion(TimeSpan? timeout = null)
public IOperationResult WaitForCompletion(CancellationToken token)

public TResult WaitForCompletion<TResult>(TimeSpan? timeout = null)
    where TResult : IOperationResult
public TResult WaitForCompletion<TResult>(CancellationToken token)
    where TResult : IOperationResult
// Available overloads:
public Task<IOperationResult> WaitForCompletionAsync(TimeSpan? timeout = null)
public Task<IOperationResult> WaitForCompletionAsync(CancellationToken token)

public async Task<TResult> WaitForCompletionAsync<TResult>(TimeSpan? timeout = null)
    where TResult : IOperationResult
public async Task<TResult> WaitForCompletionAsync<TResult>(CancellationToken token)
    where TResult : IOperationResult    
Parameter Type Description
timeout TimeSpan
  • When timespan is specified -
    The server will throw a TimeoutException if operation has Not completed within the specified time frame.
    The operation itself continues to run in the background,
    no rollback action takes place.
  • null -
    WaitForCompletion will wait for operation to complete forever.
token CancellationToken
  • When cancellation token is specified -
    The server will throw a TimeoutException if operation has Not completed at cancellation time.
    The operation itself continues to run in the background,
    no rollback action takes place.
Return type
IOperationResult The operation result content.

Kill operation:

// Define operation, e.g. delete all discontinued products 
// Note: This operation implements interface: 'IOperation<OperationIdResult>'
IOperation<OperationIdResult> deleteByQueryOp =
    new DeleteByQueryOperation("from Products where Discontinued = true");
    
// Execute the operation
// Send returns an 'Operation' object that can be 'killed'
Operation operation = documentStore.Operations.Send(deleteByQueryOp);

// Call 'Kill' to abort operation
operation.Kill();
// Define operation, e.g. delete all discontinued products 
// Note: This operation implements interface: 'IOperation<OperationIdResult>'
IOperation<OperationIdResult> deleteByQueryOp =
    new DeleteByQueryOperation("from Products where Discontinued = true");
    
// Execute the operation
// SendAsync returns an 'Operation' object that can be 'killed'
Operation operation = await documentStore.Operations.SendAsync(deleteByQueryOp);

// Call 'KillAsync' to abort operation
await operation.KillAsync();

// Assert that operation is no longer running
await Assert.ThrowsAsync<TaskCanceledException>(() => 
    operation.WaitForCompletionAsync(TimeSpan.FromSeconds(30)));
Syntax:

// Available overloads:
public void Kill()
public async Task KillAsync(CancellationToken token = default)
Parameter Type Description
token CancellationToken Provide a cancellation token if needed to abort the KillAsync method