Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ The module structure exactly mirrors the Eclipse Store Java repository for famil
- βœ… **`afs/blobstore`** - Complete Abstract File System blob storage backend
- βœ… **`afs/aws/s3`** - Complete AWS S3 storage backend
- βœ… **`afs/azure/storage`** - Complete Azure Storage backend
- 🚧 **`afs/googlecloud/firestore`** - Google Cloud Firestore integration (in progress)
- βœ… **`afs/googlecloud/firestore`** - Complete Google Cloud Firestore integration
- βœ… **`gigamap/gigamap`** - Complete high-performance indexed collections with:
- βœ… **Advanced indexing system** (bitmap, hash, unique indices)
- βœ… **Full LINQ support** for querying (Eclipse Store compatible)
Expand Down Expand Up @@ -125,7 +125,7 @@ The .NET implementation maintains the same module structure, interfaces, and des
- βœ… **Blob storage** support for large object handling
- βœ… **AWS S3** storage backend for cloud storage
- βœ… **Azure Storage** backend for Microsoft cloud
- 🚧 **Google Cloud Firestore** integration (in progress)
- βœ… **Google Cloud Firestore** integration

## Architecture

Expand Down
117 changes: 117 additions & 0 deletions afs/blobstore/src/AfsStorageConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using MessagePack;
using NebulaStore.Storage;
Expand Down Expand Up @@ -212,10 +213,126 @@
"blobstore" => new LocalBlobStoreConnector(
configuration.AfsConnectionString ?? configuration.StorageDirectory,
configuration.AfsUseCache),
"firestore" => CreateFirestoreConnector(configuration),
"azure.storage" => CreateAzureStorageConnector(configuration),
"s3" => CreateS3Connector(configuration),
_ => throw new NotSupportedException($"AFS storage type '{configuration.AfsStorageType}' is not supported")
};
}

/// <summary>
/// Creates a Google Cloud Firestore connector.
/// </summary>
/// <param name="configuration">The storage configuration</param>
/// <returns>The Firestore connector</returns>
private static IBlobStoreConnector CreateFirestoreConnector(IEmbeddedStorageConfiguration configuration)
{
try
{
// Use reflection to avoid hard dependency on Google Cloud Firestore
var firestoreAssembly = System.Reflection.Assembly.LoadFrom("NebulaStore.Afs.GoogleCloud.Firestore.dll");
var connectorType = firestoreAssembly.GetType("NebulaStore.Afs.GoogleCloud.Firestore.GoogleCloudFirestoreConnector");

if (connectorType == null)
throw new TypeLoadException("GoogleCloudFirestoreConnector type not found");

// Create FirestoreDb instance
var firestoreDbType = Type.GetType("Google.Cloud.Firestore.FirestoreDb, Google.Cloud.Firestore");
if (firestoreDbType == null)
throw new TypeLoadException("Google.Cloud.Firestore.FirestoreDb type not found. Make sure Google.Cloud.Firestore package is installed.");

var createMethod = firestoreDbType.GetMethod("Create", new[] { typeof(string) });
if (createMethod == null)
throw new MethodAccessException("FirestoreDb.Create method not found");

var projectId = configuration.AfsConnectionString ?? throw new ArgumentException("Project ID must be specified in AfsConnectionString for Firestore storage");
var firestoreDb = createMethod.Invoke(null, new object[] { projectId });

// Create connector
var factoryMethod = configuration.AfsUseCache
? connectorType.GetMethod("Caching", new[] { firestoreDbType })
: connectorType.GetMethod("New", new[] { firestoreDbType });

if (factoryMethod == null)
throw new MethodAccessException($"GoogleCloudFirestoreConnector factory method not found");

var connector = factoryMethod.Invoke(null, new[] { firestoreDb });
return (IBlobStoreConnector)connector!;
}
catch (Exception ex) when (!(ex is ArgumentException))
{
throw new NotSupportedException(
"Google Cloud Firestore connector could not be created. " +
"Make sure NebulaStore.Afs.GoogleCloud.Firestore and Google.Cloud.Firestore packages are installed.", ex);
}
}

/// <summary>
/// Creates an Azure Storage connector.
/// </summary>
/// <param name="configuration">The storage configuration</param>
/// <returns>The Azure Storage connector</returns>
private static IBlobStoreConnector CreateAzureStorageConnector(IEmbeddedStorageConfiguration configuration)
{
try
{
// Use reflection to avoid hard dependency on Azure Storage
var azureAssembly = System.Reflection.Assembly.LoadFrom("NebulaStore.Afs.Azure.Storage.dll");
var connectorType = azureAssembly.GetType("NebulaStore.Afs.Azure.Storage.AzureStorageConnector");

if (connectorType == null)
throw new TypeLoadException("AzureStorageConnector type not found");

var connectionString = configuration.AfsConnectionString ?? throw new ArgumentException("Connection string must be specified in AfsConnectionString for Azure storage");

var factoryMethod = connectorType.GetMethod("FromConnectionString", new[] { typeof(string), typeof(bool) });
if (factoryMethod == null)
throw new MethodAccessException("AzureStorageConnector.FromConnectionString method not found");

var connector = factoryMethod.Invoke(null, new object[] { connectionString, configuration.AfsUseCache });
return (IBlobStoreConnector)connector!;
}
catch (Exception ex) when (!(ex is ArgumentException))
{
throw new NotSupportedException(
"Azure Storage connector could not be created. " +
"Make sure NebulaStore.Afs.Azure.Storage and Azure.Storage.Blobs packages are installed.", ex);
}
}

/// <summary>
/// Creates an AWS S3 connector.
/// </summary>
/// <param name="configuration">The storage configuration</param>
/// <returns>The S3 connector</returns>
private static IBlobStoreConnector CreateS3Connector(IEmbeddedStorageConfiguration configuration)
{
try
{
// Use reflection to avoid hard dependency on AWS S3
var s3Assembly = System.Reflection.Assembly.LoadFrom("NebulaStore.Afs.Aws.S3.dll");
var connectorType = s3Assembly.GetType("NebulaStore.Afs.Aws.S3.AwsS3Connector");

if (connectorType == null)
throw new TypeLoadException("AwsS3Connector type not found");

var bucketName = configuration.AfsConnectionString ?? throw new ArgumentException("Bucket name must be specified in AfsConnectionString for S3 storage");

var factoryMethod = connectorType.GetMethod("FromBucketName", new[] { typeof(string), typeof(bool) });
if (factoryMethod == null)
throw new MethodAccessException("AwsS3Connector.FromBucketName method not found");

var connector = factoryMethod.Invoke(null, new object[] { bucketName, configuration.AfsUseCache });
return (IBlobStoreConnector)connector!;
}
catch (Exception ex) when (!(ex is ArgumentException))
{
throw new NotSupportedException(
"AWS S3 connector could not be created. " +
"Make sure NebulaStore.Afs.Aws.S3 and AWSSDK.S3 packages are installed.", ex);
}
}

/// <summary>
/// Registers type handlers for GigaMap serialization.
/// This enables automatic persistence of GigaMap instances following Eclipse Store patterns.
Expand Down Expand Up @@ -250,55 +367,55 @@
}

// IStorageConnection interface methods
public bool IssueGarbageCollection(TimeSpan timeBudget)

Check warning on line 370 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (macos-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.IssueGarbageCollection(TimeSpan)'

Check warning on line 370 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (ubuntu-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.IssueGarbageCollection(TimeSpan)'
{
// AFS implementation would trigger GC with time budget
return true; // Return true if GC completed within time budget
}

public void IssueFullFileCheck()

Check warning on line 376 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (macos-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.IssueFullFileCheck()'

Check warning on line 376 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (ubuntu-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.IssueFullFileCheck()'
{
// AFS implementation would check all files
}

public bool IssueFileCheck(TimeSpan timeBudget)

Check warning on line 381 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (macos-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.IssueFileCheck(TimeSpan)'

Check warning on line 381 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (ubuntu-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.IssueFileCheck(TimeSpan)'
{
// AFS implementation would check files with time budget
return true; // Return true if file check completed within time budget
}

public void IssueFullCacheCheck()

Check warning on line 387 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (macos-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.IssueFullCacheCheck()'

Check warning on line 387 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (ubuntu-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.IssueFullCacheCheck()'
{
// AFS implementation would check cache
}

public bool IssueCacheCheck(TimeSpan timeBudget)

Check warning on line 392 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (macos-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.IssueCacheCheck(TimeSpan)'

Check warning on line 392 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (ubuntu-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.IssueCacheCheck(TimeSpan)'
{
// AFS implementation would check cache with time budget
return true; // Return true if cache check completed within time budget
}

public void IssueFullBackup(DirectoryInfo backupDirectory)

Check warning on line 398 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (macos-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.IssueFullBackup(DirectoryInfo)'

Check warning on line 398 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (ubuntu-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.IssueFullBackup(DirectoryInfo)'
{
// AFS implementation would backup to directory
}

public void IssueTransactionsLogCleanup()

Check warning on line 403 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (macos-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.IssueTransactionsLogCleanup()'

Check warning on line 403 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (ubuntu-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.IssueTransactionsLogCleanup()'
{
// AFS implementation would cleanup transaction logs
}

public IStorageStatistics CreateStorageStatistics()

Check warning on line 408 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (macos-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.CreateStorageStatistics()'

Check warning on line 408 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (ubuntu-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.CreateStorageStatistics()'
{
return new AfsStorageStatistics(_configuration, _fileSystem);
}

public void ExportChannels(DirectoryInfo exportDirectory, bool performGarbageCollection)

Check warning on line 413 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (macos-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.ExportChannels(DirectoryInfo, bool)'

Check warning on line 413 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (ubuntu-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.ExportChannels(DirectoryInfo, bool)'
{
// AFS implementation would export channels
}

public void ImportFiles(DirectoryInfo importDirectory)

Check warning on line 418 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (macos-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.ImportFiles(DirectoryInfo)'

Check warning on line 418 in afs/blobstore/src/AfsStorageConnection.cs

View workflow job for this annotation

GitHub Actions / build-matrix (ubuntu-latest, 9.0.x)

Missing XML comment for publicly visible type or member 'AfsStorageConnection.ImportFiles(DirectoryInfo)'
{
// AFS implementation would import files
}
Expand Down
189 changes: 189 additions & 0 deletions afs/googlecloud/firestore/examples/FirestoreExample.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
using System;
using Google.Cloud.Firestore;
using NebulaStore.Afs.GoogleCloud.Firestore;
using NebulaStore.Storage.Embedded;
using NebulaStore.Storage.EmbeddedConfiguration;

namespace NebulaStore.Afs.GoogleCloud.Firestore.Examples;

/// <summary>
/// Example demonstrating how to use NebulaStore with Google Cloud Firestore.
/// </summary>
public class FirestoreExample
{
/// <summary>
/// Example data class for storage.
/// </summary>
public class Person
{
public string Name { get; set; } = string.Empty;
public int Age { get; set; }
public string Email { get; set; } = string.Empty;
}

/// <summary>
/// Example using the configuration-based approach.
/// </summary>
public static void ConfigurationBasedExample()
{
Console.WriteLine("=== Configuration-Based Firestore Example ===");

// Create configuration for Firestore storage
var config = EmbeddedStorageConfiguration.New()
.SetStorageDirectory("firestore-storage")
.UseFirestore("your-project-id", useCache: true)
.SetChannelCount(4)
.Build();

try
{
// Start storage with Firestore backend
using var storage = EmbeddedStorage.Foundation(config).Start();

// Create and store data
var root = storage.Root<Person>();
if (root == null)
{
root = new Person
{
Name = "John Doe",
Age = 30,
Email = "john.doe@example.com"
};
storage.SetRoot(root);
}

// Modify and store
root.Age = 31;
storage.StoreRoot();

Console.WriteLine($"Stored person: {root.Name}, Age: {root.Age}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
Console.WriteLine("Make sure you have:");
Console.WriteLine("1. A Google Cloud Project with Firestore enabled");
Console.WriteLine("2. Proper authentication configured");
Console.WriteLine("3. The Google.Cloud.Firestore package installed");
}
}

/// <summary>
/// Example using the convenience extension methods.
/// </summary>
public static void ConvenienceMethodExample()
{
Console.WriteLine("\n=== Convenience Method Firestore Example ===");

try
{
// Start with Firestore using convenience method
using var storage = EmbeddedStorageFirestoreExtensions.StartWithFirestore("your-project-id");

var root = storage.Root<Person>();
if (root == null)
{
root = new Person
{
Name = "Jane Smith",
Age = 25,
Email = "jane.smith@example.com"
};
storage.SetRoot(root);
}

Console.WriteLine($"Retrieved person: {root.Name}, Age: {root.Age}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}

/// <summary>
/// Example using direct AFS file system operations.
/// </summary>
public static void DirectAfsExample()
{
Console.WriteLine("\n=== Direct AFS Firestore Example ===");

try
{
// Create Firestore connection
var firestore = FirestoreDb.Create("your-project-id");

// Create file system with Firestore backend
using var fileSystem = EmbeddedStorageFirestoreExtensions.CreateFirestoreFileSystem("your-project-id");

// Perform direct file operations
var path = NebulaStore.Afs.Blobstore.BlobStorePath.New("my-collection", "folder", "file.txt");
var data = System.Text.Encoding.UTF8.GetBytes("Hello, Firestore!");

fileSystem.IoHandler.WriteData(path, data);
var readData = fileSystem.IoHandler.ReadData(path, 0, -1);
var content = System.Text.Encoding.UTF8.GetString(readData);

Console.WriteLine($"Stored and retrieved: {content}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}

/// <summary>
/// Example with authentication setup.
/// </summary>
public static void AuthenticationExample()
{
Console.WriteLine("\n=== Authentication Setup Example ===");

try
{
// Option 1: Using service account key file
var firestoreWithKey = new FirestoreDbBuilder
{
ProjectId = "your-project-id",
CredentialsPath = "path/to/service-account-key.json"
}.Build();

using var connector1 = GoogleCloudFirestoreConnector.New(firestoreWithKey);
Console.WriteLine("Created connector with service account key");

// Option 2: Using environment variable for credentials
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", "path/to/service-account-key.json");
var firestoreWithEnv = FirestoreDb.Create("your-project-id");

using var connector2 = GoogleCloudFirestoreConnector.Caching(firestoreWithEnv);
Console.WriteLine("Created connector with environment credentials");

// Option 3: Using emulator for testing
Environment.SetEnvironmentVariable("FIRESTORE_EMULATOR_HOST", "localhost:8080");
var firestoreEmulator = FirestoreDb.Create("test-project");

using var connector3 = GoogleCloudFirestoreConnector.New(firestoreEmulator);
Console.WriteLine("Created connector for emulator");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}

/// <summary>
/// Main entry point for the examples.
/// </summary>
public static void Main(string[] args)
{
Console.WriteLine("NebulaStore Google Cloud Firestore Integration Examples");
Console.WriteLine("=====================================================");

ConfigurationBasedExample();
ConvenienceMethodExample();
DirectAfsExample();
AuthenticationExample();

Console.WriteLine("\nFor more information, see the README.md file.");
}
}
Loading
Loading