Skip to content

7.2.0

Latest

Choose a tag to compare

@M4xymm M4xymm released this 05 Feb 12:42
· 12 commits to v7.2 since this release
a3fbe97

πŸŽ‰ What's New

☁️ Remote Attachments Support

Store attachments in cloud storage (Amazon S3 or Azure Blob Storage) to reduce database size and improve performance.

New Configuration System

  • Remote Attachments Configuration: Configure cloud storage destinations for automatic attachment uploads
    • Support for Amazon S3 with access keys, session tokens, and region configuration
    • Support for Azure Blob Storage with account key or SAS token authentication
    • S3-compatible storage service support (MinIO, Wasabi, DigitalOcean Spaces)
    • Path-style and virtual-hosted-style request options
    • Per-destination enable/disable control
    • Upload frequency, batch size, and concurrency configuration

Remote Attachment Operations

  • ConfigureRemoteAttachmentsOperation: Configure cloud storage destinations
  • GetRemoteAttachmentsConfigurationOperation: Retrieve current configuration
  • Full support in bulk insert and regular session operations

Cloud Storage Settings Classes

  • RemoteAttachmentsConfiguration: Main configuration container
  • RemoteAttachmentsDestinationConfiguration: Individual destination settings
  • RemoteAttachmentsS3Settings: Amazon S3 configuration
  • RemoteAttachmentsAzureSettings: Azure Blob Storage configuration
  • RemoteAttachmentParameters: Schedule attachment uploads to cloud storage

βœ… Schema Validation Support

Enforce JSON Schema validation on document collections to ensure data quality.

Schema Validation Configuration

  • Schema Validation Setup: Define and manage JSON Schema validators per collection
  • Disable/enable validation per collection without removing configuration
  • Support for complex nested schemas with constraints

Schema Validation Operations

  • ConfigureSchemaValidationOperation: Apply schema validation configuration
  • GetSchemaValidationConfiguration: Retrieve current validation settings

Schema Features

  • JSON Schema support (type checking, required fields, min/max values, patterns, etc.)
  • Per-collection configuration with optional disable flag
  • Backward compatible - validation can be toggled on/off

πŸ”§ Enhanced API

New Attachment Parameter Classes

  • StoreAttachmentParameters: Encapsulates all attachment storage options
    • Name, stream, content type, change vector, and remote parameters
    • Convenient builder pattern alternative to multiple method overloads
  • IStoreAttachmentParameters: Interface for attachment storage parameters
  • RemoteAttachmentFlags: Type-safe flags for remote attachment behavior
  • RemoteAttachmentParameters: Configure remote uploads with optional scheduling

Updated Attachment Interface

  • Attachment metadata now includes optional remoteParameters
  • Enhanced AttachmentDetails with remote parameter information
  • Full attachment metadata serialization/deserialization support

API Method Overloads

  • Session attachment storage now supports both traditional and parameter-based approaches:
    // Traditional approach (still supported)
    session.advanced.attachments.store(docId, name, stream, contentType);
    
    // New parameter-based approach
    session.advanced.attachments.store(docId, new StoreAttachmentParameters(...));
  • Bulk insert attachment support includes remote parameters

πŸ”„ Breaking Changes

None - This release maintains full backward compatibility.

πŸ“– Usage Examples

Configuring Remote Attachments with S3

import { 
    ConfigureRemoteAttachmentsOperation,
    RemoteAttachmentsConfiguration,
    RemoteAttachmentsDestinationConfiguration,
    RemoteAttachmentsS3Settings
} from "ravendb";

const configuration = new RemoteAttachmentsConfiguration();

const s3Destination = new RemoteAttachmentsDestinationConfiguration();
s3Destination.disabled = false;

const s3Settings = new RemoteAttachmentsS3Settings();
s3Settings.bucketName = "my-attachments-bucket";
s3Settings.awsAccessKey = "YOUR_ACCESS_KEY";
s3Settings.awsSecretKey = "YOUR_SECRET_KEY";
s3Settings.awsRegionName = "us-east-1";

s3Destination.s3Settings = s3Settings;
configuration.destinations["MyS3Storage"] = s3Destination;

await store.maintenance.send(new ConfigureRemoteAttachmentsOperation(configuration));

Configuring Remote Attachments with Azure

import {
    RemoteAttachmentsAzureSettings
} from "ravendb";

const azureSettings = new RemoteAttachmentsAzureSettings();
azureSettings.storageContainer = "my-container";
azureSettings.accountName = "myStorageAccount";
azureSettings.accountKey = "YOUR_ACCOUNT_KEY"; // Or use sasToken for SAS-based auth
azureSettings.remoteFolderName = "production/database1";

azureDestination.azureSettings = azureSettings;

Storing Attachments with Remote Parameters

import { RemoteAttachmentParameters, StoreAttachmentParameters } from "ravendb";

const session = store.openSession();

// The upload to remote storage (e.g. S3) will be executed at the scheduled time.
const uploadAt = new Date(Date.now() + 3600000); // +1 hour
const remoteParams = new RemoteAttachmentParameters("MyS3Storage", uploadAt);

// Option 1: Using parameters object
const params = new StoreAttachmentParameters(
    "invoice.pdf",
    attachmentStream,
    "application/pdf",
    null,
    remoteParams
);
session.advanced.attachments.store(documentId, params);

// Option 2: Traditional approach (immediate upload)
session.advanced.attachments.store(
    documentId,
    "invoice.pdf",
    attachmentStream,
    "application/pdf"
);

await session.saveChanges();

Bulk Insert with Remote Attachments

const bulkInsert = store.bulkInsert();

const remoteParams = new RemoteAttachmentParameters("MyS3Storage");

for (let i = 0; i < 100; i++) {
    const order = { id: `orders/${i}`, company: `Company ${i}` };
    await bulkInsert.store(order, `orders/${i}`);

    const attachmentData = Buffer.from(`Invoice data ${i}`);
    await bulkInsert.attachmentsFor(`orders/${i}`)
        .store(`invoice-${i}.pdf`, attachmentData, "application/pdf", remoteParams);
}

await bulkInsert.finish();

Configuring Schema Validation

import {
    ConfigureSchemaValidationOperation,
    GetSchemaValidationConfiguration,
    SchemaValidationConfiguration
} from "ravendb";

const userSchema = JSON.stringify({
    type: "object",
    properties: {
        age: {
            type: "integer",
            minimum: 21,
            maximum: 67
        },
        email: {
            type: "string",
            pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
        }
    },
    required: ["age", "email"]
});

const configuration: SchemaValidationConfiguration = {
    validatorsPerCollection: {
        "Users": {
            schema: userSchema
        },
        "Employees": {
            disabled: true,
            schema: userSchema
        }
    }
};

await store.maintenance.send(new ConfigureSchemaValidationOperation(configuration));

// Retrieve configuration later
const config = await store.maintenance.send(new GetSchemaValidationConfiguration());
config.validatorsPerCollection["Users"].disabled = true;
await store.maintenance.send(new ConfigureSchemaValidationOperation(config));

Disabling Schema Validation

// Get current configuration
const config = await store.maintenance.send(new GetSchemaValidationConfiguration());

// Disable validation for a specific collection
config.validatorsPerCollection["Users"].disabled = true;

// Apply changes
await store.maintenance.send(new ConfigureSchemaValidationOperation(config));

πŸ”— Related Documentation

πŸ› οΈ Migration Guide

From Previous Versions (No Breaking Changes Required)

If you're upgrading from v7.1.x:

  1. Optional: Use new parameter objects for cleaner code:

    // Old way (still works)
    session.advanced.attachments.store(id, name, stream, contentType);
    
    // New way (optional)
    session.advanced.attachments.store(id, new StoreAttachmentParameters(name, stream, contentType));
  2. Optional: Configure remote attachments if you want to use cloud storage:

     import { 
         ConfigureRemoteAttachmentsOperation,
         RemoteAttachmentsConfiguration,
         RemoteAttachmentsDestinationConfiguration,
         RemoteAttachmentsS3Settings
     } from "ravendb";
     
     const configuration = new RemoteAttachmentsConfiguration();
     
     const s3Destination = new RemoteAttachmentsDestinationConfiguration();
     s3Destination.disabled = false;
     
     const s3Settings = new RemoteAttachmentsS3Settings();
     s3Settings.bucketName = "my-attachments-bucket";
     s3Settings.awsAccessKey = "YOUR_ACCESS_KEY";
     s3Settings.awsSecretKey = "YOUR_SECRET_KEY";
     s3Settings.awsRegionName = "us-east-1";
     
     s3Destination.s3Settings = s3Settings;
     configuration.destinations["MyS3Storage"] = s3Destination;
     
     await store.maintenance.send(new ConfigureRemoteAttachmentsOperation(configuration));
  3. Optional: Add schema validation to enforce data quality:

    import {
        ConfigureSchemaValidationOperation,
        GetSchemaValidationConfiguration,
        SchemaValidationConfiguration
    } from "ravendb";
    
    const userSchema = JSON.stringify({
        type: "object",
        properties: {
            age: {
                type: "integer",
                minimum: 21,
                maximum: 67
            },
            email: {
                type: "string",
                pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
            }
        },
        required: ["age", "email"]
    });
    
    const configuration: SchemaValidationConfiguration = {
        validatorsPerCollection: {
            "Users": {
                schema: userSchema
            },
            "Employees": {
                disabled: true,
                schema: userSchema
            }
        }
    };
    
    await store.maintenance.send(new ConfigureSchemaValidationOperation(configuration));

All existing code continues to work without any changes.