Exemple #1
0
            public AzureClientHolder(AzureSettings setting, Progress progress = null, [CallerMemberName] string caller = null)
            {
                Assert.False(string.IsNullOrEmpty(setting.StorageContainer), "string.IsNullOrEmpty(setting.StorageContainer)");
                Settings = setting;

                // keep only alphanumeric characters
                Settings.RemoteFolderName = _remoteFolder = GetRemoteFolder(caller);
                Client = RavenAzureClient.Create(Settings, DefaultConfiguration, progress);
            }
Exemple #2
0
        private void DeleteFromAzure(AzureSettings settings)
        {
            using (var client = RavenAzureClient.Create(settings, _settings.Configuration, progress: null, TaskCancelToken.Token))
            {
                var key = CombinePathAndKey(settings.RemoteFolderName);
                client.DeleteBlobs(new List <string> {
                    key
                });

                if (_logger.IsInfoEnabled)
                {
                    _logger.Info($"{ReportDeletion(AzureName)} container: {settings.StorageContainer}, with key: {key}");
                }
            }
        }
        private void UploadToAzure(AzureSettings settings, Stream stream, Progress progress)
        {
            using (var client = RavenAzureClient.Create(settings, _settings.Configuration, progress, TaskCancelToken.Token))
            {
                var key = CombinePathAndKey(settings.RemoteFolderName);
                client.PutBlob(key, stream, new Dictionary <string, string>
                {
                    { "Description", GetArchiveDescription() }
                });

                if (_logger.IsInfoEnabled)
                {
                    _logger.Info($"{ReportSuccess(AzureName)} container: {settings.StorageContainer}, with key: {key}");
                }

                var runner = new AzureRetentionPolicyRunner(_retentionPolicyParameters, client);
                runner.Execute();
            }
        }
Exemple #4
0
        private static async Task DeleteObjects(AzureSettings azureSettings, string prefix, string delimiter, bool listFolder = false)
        {
            if (azureSettings == null)
            {
                return;
            }

            try
            {
                using (var client = RavenAzureClient.Create(azureSettings, DefaultBackupConfiguration))
                {
                    var result = await client.ListBlobsAsync(prefix, delimiter, listFolder);

                    List <string> filesToDelete;

                    if (listFolder == false)
                    {
                        filesToDelete = result.List.Select(b => b.Name).ToList();
                    }
                    else
                    {
                        filesToDelete = await ListAllFilesInFolders(client, result.List);
                    }

                    if (filesToDelete.Count == 0)
                    {
                        return;
                    }

                    client.DeleteBlobs(filesToDelete);
                }
            }
            catch (Exception)
            {
                // ignored
            }
        }
        public async Task GetFolderPathOptions()
        {
            PeriodicBackupConnectionType connectionType;
            var type = GetStringValuesQueryString("type", false).FirstOrDefault();

            if (type == null)
            {
                //Backward compatibility
                connectionType = PeriodicBackupConnectionType.Local;
            }
            else if (Enum.TryParse(type, out connectionType) == false)
            {
                throw new ArgumentException($"Query string '{type}' was not recognized as valid type");
            }

            using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext context))
            {
                var folderPathOptions = new FolderPathOptions();
                ;
                switch (connectionType)
                {
                case PeriodicBackupConnectionType.Local:
                    var isBackupFolder = GetBoolValueQueryString("backupFolder", required: false) ?? false;
                    var path           = GetStringQueryString("path", required: false);
                    folderPathOptions = FolderPath.GetOptions(path, isBackupFolder, ServerStore.Configuration);
                    break;

                case PeriodicBackupConnectionType.S3:
                    var json = await context.ReadForMemoryAsync(RequestBodyStream(), "studio-tasks/format");

                    if (connectionType != PeriodicBackupConnectionType.Local && json == null)
                    {
                        throw new BadRequestException("No JSON was posted.");
                    }

                    var s3Settings = JsonDeserializationServer.S3Settings(json);
                    if (s3Settings == null)
                    {
                        throw new BadRequestException("No S3Settings were found.");
                    }

                    if (string.IsNullOrWhiteSpace(s3Settings.AwsAccessKey) ||
                        string.IsNullOrWhiteSpace(s3Settings.AwsSecretKey) ||
                        string.IsNullOrWhiteSpace(s3Settings.BucketName) ||
                        string.IsNullOrWhiteSpace(s3Settings.AwsRegionName))
                    {
                        break;
                    }

                    using (var client = new RavenAwsS3Client(s3Settings, ServerStore.Configuration.Backup))
                    {
                        // fetching only the first 64 results for the auto complete
                        var folders = await client.ListObjectsAsync(s3Settings.RemoteFolderName, "/", true, take : 64);

                        if (folders != null)
                        {
                            foreach (var folder in folders.FileInfoDetails)
                            {
                                var fullPath = folder.FullPath;
                                if (string.IsNullOrWhiteSpace(fullPath))
                                {
                                    continue;
                                }

                                folderPathOptions.List.Add(fullPath);
                            }
                        }
                    }
                    break;

                case PeriodicBackupConnectionType.Azure:
                    var azureJson = await context.ReadForMemoryAsync(RequestBodyStream(), "studio-tasks/format");

                    if (connectionType != PeriodicBackupConnectionType.Local && azureJson == null)
                    {
                        throw new BadRequestException("No JSON was posted.");
                    }

                    var azureSettings = JsonDeserializationServer.AzureSettings(azureJson);
                    if (azureSettings == null)
                    {
                        throw new BadRequestException("No AzureSettings were found.");
                    }

                    if (string.IsNullOrWhiteSpace(azureSettings.AccountName) ||
                        string.IsNullOrWhiteSpace(azureSettings.AccountKey) ||
                        string.IsNullOrWhiteSpace(azureSettings.StorageContainer))
                    {
                        break;
                    }

                    using (var client = RavenAzureClient.Create(azureSettings, ServerStore.Configuration.Backup))
                    {
                        var folders = (await client.ListBlobsAsync(azureSettings.RemoteFolderName, "/", true));

                        foreach (var folder in folders.List)
                        {
                            var fullPath = folder.Name;
                            if (string.IsNullOrWhiteSpace(fullPath))
                            {
                                continue;
                            }

                            folderPathOptions.List.Add(fullPath);
                        }
                    }
                    break;

                case PeriodicBackupConnectionType.GoogleCloud:
                    var googleCloudJson = await context.ReadForMemoryAsync(RequestBodyStream(), "studio-tasks/format");

                    if (connectionType != PeriodicBackupConnectionType.Local && googleCloudJson == null)
                    {
                        throw new BadRequestException("No JSON was posted.");
                    }

                    var googleCloudSettings = JsonDeserializationServer.GoogleCloudSettings(googleCloudJson);
                    if (googleCloudSettings == null)
                    {
                        throw new BadRequestException("No AzureSettings were found.");
                    }

                    if (string.IsNullOrWhiteSpace(googleCloudSettings.BucketName) ||
                        string.IsNullOrWhiteSpace(googleCloudSettings.GoogleCredentialsJson))
                    {
                        break;
                    }

                    using (var client = new RavenGoogleCloudClient(googleCloudSettings, ServerStore.Configuration.Backup))
                    {
                        var folders             = (await client.ListObjectsAsync(googleCloudSettings.RemoteFolderName));
                        var requestedPathLength = googleCloudSettings.RemoteFolderName.Split('/').Length;

                        foreach (var folder in folders)
                        {
                            const char separator = '/';
                            var        splitted  = folder.Name.Split(separator);
                            var        result    = string.Join(separator, splitted.Take(requestedPathLength)) + separator;

                            if (string.IsNullOrWhiteSpace(result))
                            {
                                continue;
                            }

                            folderPathOptions.List.Add(result);
                        }
                    }
                    break;

                case PeriodicBackupConnectionType.FTP:
                case PeriodicBackupConnectionType.Glacier:
                    throw new NotSupportedException();

                default:
                    throw new ArgumentOutOfRangeException();
                }

                await using (var writer = new AsyncBlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    context.Write(writer, new DynamicJsonValue
                    {
                        [nameof(FolderPathOptions.List)] = TypeConverter.ToBlittableSupportedType(folderPathOptions.List)
                    });
                }
            }
        }
        public async Task TestPeriodicBackupCredentials()
        {
            var type = GetQueryStringValueAndAssertIfSingleAndNotEmpty("type");

            if (Enum.TryParse(type, out PeriodicBackupConnectionType connectionType) == false)
            {
                throw new ArgumentException($"Unknown backup connection: {type}");
            }

            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
            {
                DynamicJsonValue result;
                try
                {
                    var connectionInfo = await context.ReadForMemoryAsync(RequestBodyStream(), "test-connection");

                    switch (connectionType)
                    {
                    case PeriodicBackupConnectionType.S3:
                        var s3Settings = JsonDeserializationClient.S3Settings(connectionInfo);
                        using (var awsClient = new RavenAwsS3Client(s3Settings, ServerStore.Configuration.Backup, cancellationToken: ServerStore.ServerShutdown))
                        {
                            awsClient.TestConnection();
                        }
                        break;

                    case PeriodicBackupConnectionType.Glacier:
                        var glacierSettings = JsonDeserializationClient.GlacierSettings(connectionInfo);
                        using (var glacierClient = new RavenAwsGlacierClient(glacierSettings, ServerStore.Configuration.Backup, cancellationToken: ServerStore.ServerShutdown))
                        {
                            glacierClient.TestConnection();
                        }
                        break;

                    case PeriodicBackupConnectionType.Azure:
                        var azureSettings = JsonDeserializationClient.AzureSettings(connectionInfo);
                        using (var azureClient = RavenAzureClient.Create(azureSettings, ServerStore.Configuration.Backup, cancellationToken: ServerStore.ServerShutdown))
                        {
                            azureClient.TestConnection();
                        }
                        break;

                    case PeriodicBackupConnectionType.GoogleCloud:
                        var googleCloudSettings = JsonDeserializationClient.GoogleCloudSettings(connectionInfo);
                        using (var googleCloudClient = new RavenGoogleCloudClient(googleCloudSettings, ServerStore.Configuration.Backup, cancellationToken: ServerStore.ServerShutdown))
                        {
                            await googleCloudClient.TestConnection();
                        }
                        break;

                    case PeriodicBackupConnectionType.FTP:
                        var ftpSettings = JsonDeserializationClient.FtpSettings(connectionInfo);
                        using (var ftpClient = new RavenFtpClient(ftpSettings))
                        {
                            ftpClient.TestConnection();
                        }
                        break;

                    case PeriodicBackupConnectionType.Local:
                    case PeriodicBackupConnectionType.None:
                    default:
                        throw new ArgumentOutOfRangeException();
                    }

                    result = new DynamicJsonValue
                    {
                        [nameof(NodeConnectionTestResult.Success)] = true,
                    };
                }
                catch (Exception e)
                {
                    result = new DynamicJsonValue
                    {
                        [nameof(NodeConnectionTestResult.Success)] = false,
                        [nameof(NodeConnectionTestResult.Error)]   = e.ToString()
                    };
                }

                await using (var writer = new AsyncBlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    context.Write(writer, result);
                }
            }
        }
 public AzureRestorePoints(BackupConfiguration configuration, SortedList <DateTime, RestorePoint> sortedList, TransactionOperationContext context, AzureSettings azureSettings) : base(sortedList, context)
 {
     _client = RavenAzureClient.Create(azureSettings, configuration);
 }
Exemple #8
0
        public async Task CanUseCustomPrefix()
        {
            var settings = GetAzureSettings();

            try
            {
                using (var store = GetDocumentStore())
                {
                    var baseline = new DateTime(2020, 1, 1);

                    using (var session = store.OpenAsyncSession())
                    {
                        for (int i = 0; i < 31; i++)
                        {
                            await session.StoreAsync(new Order
                            {
                                Id        = $"orders/{i}",
                                OrderedAt = baseline.AddDays(i),
                                ShipVia   = $"shippers/{i}",
                                Company   = $"companies/{i}"
                            });
                        }

                        for (int i = 0; i < 28; i++)
                        {
                            await session.StoreAsync(new Order
                            {
                                Id        = $"orders/{i + 31}",
                                OrderedAt = baseline.AddMonths(1).AddDays(i),
                                ShipVia   = $"shippers/{i + 31}",
                                Company   = $"companies/{i + 31}"
                            });
                        }

                        await session.SaveChangesAsync();
                    }

                    var          script          = @"
var orderDate = new Date(this.OrderedAt);
var year = orderDate.getFullYear();
var month = orderDate.getMonth() + 1;

loadToOrders(partitionBy(['year', year], ['month', month], ['source', $customPartitionValue]),
{
    Company : this.Company,
    ShipVia : this.ShipVia
});
";
                    const string customPartition = "shop-16";
                    var          etlDone         = WaitForEtl(store, (n, statistics) => statistics.LoadSuccesses != 0);
                    SetupAzureEtl(store, script, settings, customPartition);

                    etlDone.Wait(TimeSpan.FromMinutes(1));

                    using (var client = RavenAzureClient.Create(settings, DefaultBackupConfiguration))
                    {
                        var prefix       = $"{settings.RemoteFolderName}/{CollectionName}";
                        var cloudObjects = await client.ListBlobsAsync(prefix, delimiter : string.Empty, listFolders : false);

                        var list = cloudObjects.List.ToList();

                        Assert.Equal(2, list.Count);
                        Assert.Contains($"/Orders/year=2020/month=1/source={customPartition}/", list[0].Name);
                        Assert.Contains($"/Orders/year=2020/month=2/source={customPartition}/", list[1].Name);
                    }
                }
            }

            finally
            {
                await DeleteObjects(settings, prefix : $"{settings.RemoteFolderName}/{CollectionName}", delimiter : string.Empty);
            }
        }
Exemple #9
0
        public async Task SimpleTransformation_MultiplePartitions()
        {
            var settings = GetAzureSettings();
            var prefix   = $"{settings.RemoteFolderName}/{CollectionName}/";

            try
            {
                using (var store = GetDocumentStore())
                {
                    var baseline = DateTime.SpecifyKind(new DateTime(2020, 1, 1), DateTimeKind.Utc);

                    using (var session = store.OpenAsyncSession())
                    {
                        const int total = 31 + 28; // days in January + days in February

                        for (int i = 0; i < total; i++)
                        {
                            var orderedAt = baseline.AddDays(i);
                            await session.StoreAsync(new Order
                            {
                                Id        = $"orders/{i}",
                                OrderedAt = orderedAt,
                                RequireAt = orderedAt.AddDays(7),
                                ShipVia   = $"shippers/{i}",
                                Company   = $"companies/{i}"
                            });
                        }

                        for (int i = 1; i <= 37; i++)
                        {
                            var index     = i + total;
                            var orderedAt = baseline.AddYears(1).AddMonths(1).AddDays(i);
                            await session.StoreAsync(new Order
                            {
                                Id        = $"orders/{index}",
                                OrderedAt = orderedAt,
                                RequireAt = orderedAt.AddDays(7),
                                ShipVia   = $"shippers/{index}",
                                Company   = $"companies/{index}"
                            });
                        }

                        await session.SaveChangesAsync();
                    }

                    var etlDone = WaitForEtl(store, (n, statistics) => statistics.LoadSuccesses != 0 && statistics.LoadErrors == 0);

                    var script = @"
var orderDate = new Date(this.OrderedAt);

loadToOrders(partitionBy(
    ['year', orderDate.getFullYear()],
    ['month', orderDate.getMonth() + 1]
),
    {
        Company : this.Company,
        ShipVia : this.ShipVia,
        RequireAt : this.RequireAt
    });
";
                    SetupAzureEtl(store, script, settings);

                    etlDone.Wait(TimeSpan.FromMinutes(1));

                    var expectedFields = new[] { "RequireAt", "ShipVia", "Company", ParquetTransformedItems.DefaultIdColumn, ParquetTransformedItems.LastModifiedColumn };

                    using (var client = RavenAzureClient.Create(settings, DefaultBackupConfiguration))
                    {
                        var cloudObjects = await client.ListBlobsAsync(prefix, delimiter : "/", listFolders : true);

                        var list = cloudObjects.List.ToList();

                        Assert.Equal(2, list.Count);
                        Assert.Contains("Orders/year=2020/", list[0].Name);
                        Assert.Contains("Orders/year=2021/", list[1].Name);

                        for (var index = 1; index <= list.Count; index++)
                        {
                            var folder          = list[index - 1];
                            var objectsInFolder = await client.ListBlobsAsync(prefix : folder.Name, delimiter : "/", listFolders : true);

                            var objects = objectsInFolder.List.ToList();
                            Assert.Equal(2, objects.Count);
                            Assert.Contains($"month={index}/", objects[0].Name);
                            Assert.Contains($"month={index + 1}/", objects[1].Name);
                        }

                        var files = await ListAllFilesInFolders(client, list);

                        Assert.Equal(4, files.Count);

                        foreach (var filePath in files)
                        {
                            var blob = await client.GetBlobAsync(filePath);

                            await using var ms = new MemoryStream();
                            blob.Data.CopyTo(ms);

                            using (var parquetReader = new ParquetReader(ms))
                            {
                                Assert.Equal(1, parquetReader.RowGroupCount);
                                Assert.Equal(expectedFields.Length, parquetReader.Schema.Fields.Count);

                                using var rowGroupReader = parquetReader.OpenRowGroupReader(0);
                                foreach (var field in parquetReader.Schema.Fields)
                                {
                                    Assert.True(field.Name.In(expectedFields));
                                    var data = rowGroupReader.ReadColumn((DataField)field).Data;

                                    Assert.True(data.Length == 31 || data.Length == 28 || data.Length == 27 || data.Length == 10);
                                    if (field.Name != "RequireAt")
                                    {
                                        continue;
                                    }

                                    var count = data.Length switch
                                    {
                                        31 => 0,
                                        28 => 31,
                                        27 => 365 + 33,
                                        10 => 365 + 33 + 27,
                                        _ => throw new ArgumentOutOfRangeException()
                                    };

                                    foreach (var val in data)
                                    {
                                        var expectedOrderDate = new DateTimeOffset(DateTime.SpecifyKind(baseline.AddDays(count++), DateTimeKind.Utc));
                                        var expected          = expectedOrderDate.AddDays(7);
                                        Assert.Equal(expected, val);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            finally
            {
                await DeleteObjects(settings, prefix, delimiter : "/", listFolder : true);
            }
        }
Exemple #10
0
        public async Task SimpleTransformation_NoPartition()
        {
            var settings = GetAzureSettings();

            try
            {
                using (var store = GetDocumentStore())
                {
                    var baseline = new DateTime(2020, 1, 1).ToUniversalTime();

                    using (var session = store.OpenAsyncSession())
                    {
                        for (int i = 0; i < 100; i++)
                        {
                            await session.StoreAsync(new Order
                            {
                                Id        = $"orders/{i}",
                                OrderedAt = baseline.AddDays(i),
                                ShipVia   = $"shippers/{i}",
                                Company   = $"companies/{i}"
                            });
                        }

                        await session.SaveChangesAsync();
                    }

                    var etlDone = WaitForEtl(store, (n, statistics) => statistics.LoadSuccesses != 0);

                    var script = @"
loadToOrders(noPartition(),
    {
        OrderDate : this.OrderedAt
        Company : this.Company,
        ShipVia : this.ShipVia
    });
";
                    SetupAzureEtl(store, script, settings);

                    etlDone.Wait(TimeSpan.FromMinutes(1));

                    using (var client = RavenAzureClient.Create(settings, DefaultBackupConfiguration))
                    {
                        var prefix = $"{settings.RemoteFolderName}/{CollectionName}";

                        var cloudObjects = await client.ListBlobsAsync(prefix, delimiter : string.Empty, listFolders : false);

                        var list = cloudObjects.List.ToList();

                        Assert.Equal(1, list.Count);

                        var blob = await client.GetBlobAsync(list[0].Name);

                        await using var ms = new MemoryStream();
                        blob.Data.CopyTo(ms);

                        using (var parquetReader = new ParquetReader(ms))
                        {
                            Assert.Equal(1, parquetReader.RowGroupCount);

                            var expectedFields = new[] { "OrderDate", "ShipVia", "Company", ParquetTransformedItems.DefaultIdColumn, ParquetTransformedItems.LastModifiedColumn };

                            Assert.Equal(expectedFields.Length, parquetReader.Schema.Fields.Count);

                            using var rowGroupReader = parquetReader.OpenRowGroupReader(0);
                            foreach (var field in parquetReader.Schema.Fields)
                            {
                                Assert.True(field.Name.In(expectedFields));

                                var data = rowGroupReader.ReadColumn((DataField)field).Data;
                                Assert.True(data.Length == 100);

                                if (field.Name == ParquetTransformedItems.LastModifiedColumn)
                                {
                                    continue;
                                }

                                var count = 0;
                                foreach (var val in data)
                                {
                                    if (field.Name == "OrderDate")
                                    {
                                        var expectedDto = new DateTimeOffset(DateTime.SpecifyKind(baseline.AddDays(count), DateTimeKind.Utc));
                                        Assert.Equal(expectedDto, val);
                                    }

                                    else
                                    {
                                        var expected = field.Name switch
                                        {
                                            ParquetTransformedItems.DefaultIdColumn => $"orders/{count}",
                                            "Company" => $"companies/{count}",
                                            "ShipVia" => $"shippers/{count}",
                                            _ => null
                                        };

                                        Assert.Equal(expected, val);
                                    }

                                    count++;
                                }
                            }
                        }
                    }
                }
            }
            finally
            {
                await DeleteObjects(settings);
            }
        }
Exemple #11
0
        public async Task CanModifyPartitionColumnName()
        {
            var settings = GetAzureSettings();

            try
            {
                using (var store = GetDocumentStore())
                {
                    const string partitionColumn = "order_date";

                    var baseline = new DateTime(2020, 1, 1);

                    using (var session = store.OpenAsyncSession())
                    {
                        for (int i = 0; i < 31; i++)
                        {
                            await session.StoreAsync(new Order
                            {
                                Id        = $"orders/{i}",
                                OrderedAt = baseline.AddDays(i),
                                ShipVia   = $"shippers/{i}",
                                Company   = $"companies/{i}"
                            });
                        }

                        for (int i = 0; i < 28; i++)
                        {
                            await session.StoreAsync(new Order
                            {
                                Id        = $"orders/{i + 31}",
                                OrderedAt = baseline.AddMonths(1).AddDays(i),
                                ShipVia   = $"shippers/{i + 31}",
                                Company   = $"companies/{i + 31}"
                            });
                        }

                        await session.SaveChangesAsync();
                    }

                    var etlDone = WaitForEtl(store, (n, statistics) => statistics.LoadSuccesses != 0);

                    var script = @"
var orderDate = new Date(this.OrderedAt);
var year = orderDate.getFullYear();
var month = orderDate.getMonth();
var key = new Date(year, month);

loadToOrders(partitionBy(['order_date', key]),
    {
        Company : this.Company,
        ShipVia : this.ShipVia
    })
";
                    var connectionStringName = $"{store.Database} to Azure";

                    var configuration = new OlapEtlConfiguration
                    {
                        Name = "olap-azure-test",
                        ConnectionStringName = connectionStringName,
                        RunFrequency         = LocalTests.DefaultFrequency,
                        Transforms           =
                        {
                            new Transformation
                            {
                                Name        = "MonthlyOrders",
                                Collections = new List <string>{
                                    "Orders"
                                },
                                Script = script
                            }
                        }
                    };

                    SetupAzureEtl(store, settings, configuration);

                    etlDone.Wait(TimeSpan.FromMinutes(1));

                    using (var client = RavenAzureClient.Create(settings, DefaultBackupConfiguration))
                    {
                        var prefix       = $"{settings.RemoteFolderName}/{CollectionName}";
                        var cloudObjects = await client.ListBlobsAsync(prefix, string.Empty, false);

                        var list = cloudObjects.List.ToList();

                        Assert.Equal(2, list.Count);
                        Assert.Contains($"{partitionColumn}=2020-01-01", list[0].Name);
                        Assert.Contains($"{partitionColumn}=2020-02-01", list[1].Name);
                    }
                }
            }

            finally
            {
                await DeleteObjects(settings);
            }
        }
Exemple #12
0
        public async Task CanUploadToAzure()
        {
            var settings = GetAzureSettings();

            try
            {
                using (var store = GetDocumentStore())
                {
                    var baseline = new DateTime(2020, 1, 1);

                    using (var session = store.OpenAsyncSession())
                    {
                        for (int i = 0; i < 31; i++)
                        {
                            await session.StoreAsync(new Order
                            {
                                Id        = $"orders/{i}",
                                OrderedAt = baseline.AddDays(i),
                                ShipVia   = $"shippers/{i}",
                                Company   = $"companies/{i}"
                            });
                        }

                        for (int i = 0; i < 28; i++)
                        {
                            await session.StoreAsync(new Order
                            {
                                Id        = $"orders/{i + 31}",
                                OrderedAt = baseline.AddMonths(1).AddDays(i),
                                ShipVia   = $"shippers/{i + 31}",
                                Company   = $"companies/{i + 31}"
                            });
                        }

                        await session.SaveChangesAsync();
                    }

                    var etlDone = WaitForEtl(store, (n, statistics) => statistics.LoadSuccesses != 0);

                    var script = @"
var orderDate = new Date(this.OrderedAt);
var year = orderDate.getFullYear();
var month = orderDate.getMonth();
var key = new Date(year, month);

loadToOrders(partitionBy(key),
    {
        Company : this.Company,
        ShipVia : this.ShipVia
    })
";
                    SetupAzureEtl(store, script, settings);

                    etlDone.Wait(TimeSpan.FromMinutes(1));

                    using (var client = RavenAzureClient.Create(settings, DefaultBackupConfiguration))
                    {
                        var prefix = $"{settings.RemoteFolderName}/{CollectionName}";
                        var result = await client.ListBlobsAsync(prefix, delimiter : string.Empty, listFolders : false);

                        var list = result.List.ToList();

                        Assert.Equal(2, list.Count);
                        Assert.Contains("2020-01-01", list[0].Name);
                        Assert.Contains("2020-02-01", list[1].Name);
                    }
                }
            }

            finally
            {
                await DeleteObjects(settings);
            }
        }
Exemple #13
0
        public async Task CanLoadToMultipleTables()
        {
            const string salesTableName = "Sales";
            var          settings       = GetAzureSettings();

            try
            {
                using (var store = GetDocumentStore())
                {
                    var baseline = new DateTime(2020, 1, 1);

                    using (var session = store.OpenAsyncSession())
                    {
                        for (int i = 0; i < 31; i++)
                        {
                            var orderedAt = baseline.AddDays(i);
                            var lines     = new List <OrderLine>();

                            for (int j = 1; j <= 5; j++)
                            {
                                lines.Add(new OrderLine
                                {
                                    Quantity     = j * 10,
                                    PricePerUnit = i + j,
                                    Product      = $"Products/{j}"
                                });
                            }

                            var o = new Order
                            {
                                Id        = $"orders/{i}",
                                OrderedAt = orderedAt,
                                RequireAt = orderedAt.AddDays(7),
                                Company   = $"companies/{i}",
                                Lines     = lines
                            };

                            await session.StoreAsync(o);
                        }

                        baseline = baseline.AddMonths(1);

                        for (int i = 0; i < 28; i++)
                        {
                            var orderedAt = baseline.AddDays(i);
                            var lines     = new List <OrderLine>();

                            for (int j = 1; j <= 5; j++)
                            {
                                lines.Add(new OrderLine
                                {
                                    Quantity     = j * 10,
                                    PricePerUnit = i + j,
                                    Product      = $"Products/{j}"
                                });
                            }

                            var o = new Order
                            {
                                Id        = $"orders/{i + 31}",
                                OrderedAt = orderedAt,
                                RequireAt = orderedAt.AddDays(7),
                                Company   = $"companies/{i}",
                                Lines     = lines
                            };

                            await session.StoreAsync(o);
                        }

                        await session.SaveChangesAsync();
                    }

                    var etlDone = WaitForEtl(store, (n, statistics) => statistics.LoadSuccesses != 0);

                    var script = @"
var orderData = {
    Company : this.Company,
    RequireAt : new Date(this.RequireAt),
    ItemsCount: this.Lines.length,
    TotalCost: 0
};

var orderDate = new Date(this.OrderedAt);
var year = orderDate.getFullYear();
var month = orderDate.getMonth();
var key = new Date(year, month);

for (var i = 0; i < this.Lines.length; i++) {
    var line = this.Lines[i];
    orderData.TotalCost += (line.PricePerUnit * line.Quantity);
    
    // load to 'sales' table

    loadToSales(partitionBy(key), {
        Qty: line.Quantity,
        Product: line.Product,
        Cost: line.PricePerUnit
    });
}

// load to 'orders' table
loadToOrders(partitionBy(key), orderData);
";


                    SetupAzureEtl(store, script, settings);
                    etlDone.Wait(TimeSpan.FromMinutes(1));

                    using (var client = RavenAzureClient.Create(settings, DefaultBackupConfiguration))
                    {
                        var prefix = $"{settings.RemoteFolderName}/{CollectionName}";
                        var result = await client.ListBlobsAsync(prefix, delimiter : string.Empty, listFolders : false);

                        var list = result.List.ToList();

                        Assert.Equal(2, list.Count);
                        Assert.Contains("2020-01-01", list[0].Name);
                        Assert.Contains("2020-02-01", list[1].Name);

                        var blob = await client.GetBlobAsync(list[0].Name);

                        await using var ms = new MemoryStream();
                        blob.Data.CopyTo(ms);

                        using (var parquetReader = new ParquetReader(ms))
                        {
                            Assert.Equal(1, parquetReader.RowGroupCount);

                            var expectedFields = new[] { "Company", "RequireAt", "ItemsCount", "TotalCost", ParquetTransformedItems.DefaultIdColumn, ParquetTransformedItems.LastModifiedColumn };
                            Assert.Equal(expectedFields.Length, parquetReader.Schema.Fields.Count);

                            using var rowGroupReader = parquetReader.OpenRowGroupReader(0);
                            foreach (var field in parquetReader.Schema.Fields)
                            {
                                Assert.True(field.Name.In(expectedFields));

                                var data = rowGroupReader.ReadColumn((DataField)field).Data;
                                Assert.True(data.Length == 31);
                            }
                        }
                    }

                    //sales
                    using (var client = RavenAzureClient.Create(settings, DefaultBackupConfiguration))
                    {
                        var prefix = $"{settings.RemoteFolderName}/{salesTableName}";
                        var result = await client.ListBlobsAsync(prefix, delimiter : string.Empty, listFolders : false);

                        var list = result.List.ToList();

                        Assert.Equal(2, list.Count);
                        Assert.Contains("2020-01-01", list[0].Name);
                        Assert.Contains("2020-02-01", list[1].Name);

                        var blob = await client.GetBlobAsync(list[1].Name);

                        await using var ms = new MemoryStream();
                        blob.Data.CopyTo(ms);

                        using (var parquetReader = new ParquetReader(ms))
                        {
                            Assert.Equal(1, parquetReader.RowGroupCount);

                            var expectedFields = new[] { "Qty", "Product", "Cost", ParquetTransformedItems.DefaultIdColumn, ParquetTransformedItems.LastModifiedColumn };
                            Assert.Equal(expectedFields.Length, parquetReader.Schema.Fields.Count);

                            using var rowGroupReader = parquetReader.OpenRowGroupReader(0);
                            foreach (var field in parquetReader.Schema.Fields)
                            {
                                Assert.True(field.Name.In(expectedFields));

                                var data = rowGroupReader.ReadColumn((DataField)field).Data;
                                Assert.True(data.Length == 28 * 5);
                            }
                        }
                    }
                }
            }
            finally
            {
                await DeleteObjects(settings, salesTableName);
            }
        }
Exemple #14
0
        public async Task SimpleTransformation()
        {
            var settings = GetAzureSettings();

            try
            {
                using (var store = GetDocumentStore())
                {
                    var baseline = new DateTime(2020, 1, 1);

                    using (var session = store.OpenAsyncSession())
                    {
                        for (int i = 1; i <= 10; i++)
                        {
                            var o = new Order
                            {
                                Id        = $"orders/{i}",
                                OrderedAt = baseline.AddDays(i),
                                Company   = $"companies/{i}",
                                ShipVia   = $"shippers/{i}"
                            };

                            await session.StoreAsync(o);
                        }

                        await session.SaveChangesAsync();
                    }

                    var etlDone = WaitForEtl(store, (n, statistics) => statistics.LoadSuccesses != 0);

                    var script = @"
var orderDate = new Date(this.OrderedAt);
var year = orderDate.getFullYear();
var month = orderDate.getMonth();
var key = new Date(year, month);

loadToOrders(partitionBy(key),
    {
        Company : this.Company,
        ShipVia : this.ShipVia
    })
";
                    SetupAzureEtl(store, script, settings);

                    etlDone.Wait(TimeSpan.FromMinutes(1));

                    using (var client = RavenAzureClient.Create(settings, DefaultBackupConfiguration))
                    {
                        var prefix = $"{settings.RemoteFolderName}/{CollectionName}";
                        var result = await client.ListBlobsAsync(prefix, delimiter : string.Empty, listFolders : false);

                        var list = result.List.ToList();
                        Assert.Equal(1, list.Count);

                        var blob = await client.GetBlobAsync(list[0].Name);

                        await using var ms = new MemoryStream();
                        blob.Data.CopyTo(ms);

                        using (var parquetReader = new ParquetReader(ms))
                        {
                            Assert.Equal(1, parquetReader.RowGroupCount);

                            var expectedFields = new[] { "Company", "ShipVia", ParquetTransformedItems.DefaultIdColumn, ParquetTransformedItems.LastModifiedColumn };

                            Assert.Equal(expectedFields.Length, parquetReader.Schema.Fields.Count);

                            using var rowGroupReader = parquetReader.OpenRowGroupReader(0);
                            foreach (var field in parquetReader.Schema.Fields)
                            {
                                Assert.True(field.Name.In(expectedFields));

                                var data = rowGroupReader.ReadColumn((DataField)field).Data;
                                Assert.True(data.Length == 10);

                                if (field.Name == ParquetTransformedItems.LastModifiedColumn)
                                {
                                    continue;
                                }

                                var count = 1;
                                foreach (var val in data)
                                {
                                    switch (field.Name)
                                    {
                                    case ParquetTransformedItems.DefaultIdColumn:
                                        Assert.Equal($"orders/{count}", val);
                                        break;

                                    case "Company":
                                        Assert.Equal($"companies/{count}", val);
                                        break;

                                    case "ShipVia":
                                        Assert.Equal($"shippers/{count}", val);
                                        break;
                                    }

                                    count++;
                                }
                            }
                        }
                    }
                }
            }

            finally
            {
                await DeleteObjects(settings);
            }
        }
 public RestoreFromAzure(ServerStore serverStore, RestoreFromAzureConfiguration restoreFromConfiguration, string nodeTag, OperationCancelToken operationCancelToken) : base(serverStore, restoreFromConfiguration, nodeTag, operationCancelToken)
 {
     _client           = RavenAzureClient.Create(restoreFromConfiguration.Settings, serverStore.Configuration.Backup);
     _remoteFolderName = restoreFromConfiguration.Settings.RemoteFolderName;
 }