Skip to content

Commit e862a62

Browse files
author
Valdis Iljuconoks
committed
Added command execution timeout configuration option for EF Core DbContext
1 parent c230c73 commit e862a62

File tree

11 files changed

+134
-101
lines changed

11 files changed

+134
-101
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [3.0.2]
6+
7+
* Added command execution timeout configuration option for EF Core DbContext
8+
59
## [3.0.1]
610

711
* Fixed issue with internationalized domain name (https://github.com/Geta/geta-optimizely-productfeed/issues/14)

sandbox/Quicksilver/EPiServer.Reference.Commerce.Site/Startup.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ public void ConfigureServices(IServiceCollection services)
124124
.AddProductFeed<MyCommerceProductRecord>(options =>
125125
{
126126
options.ConnectionString = _configuration.GetConnectionString("EPiServerDB");
127+
options.CommandTimeout = TimeSpan.FromMinutes(1);
127128

128129
options.SetEntityMapper<EntityMapper>();
129130

src/Geta.Optimizely.ProductFeed.Csv/Geta.Optimizely.ProductFeed.Csv.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
<PropertyGroup>
44
<TargetFramework>net6.0</TargetFramework>
5-
<Version>3.0.1</Version>
6-
<PackageVersion>3.0.1</PackageVersion>
5+
<Version>3.0.2</Version>
6+
<PackageVersion>3.0.2</PackageVersion>
77
<PackageId>Geta.Optimizely.ProductFeed.Csv</PackageId>
88
<Title>Geta Optimizely Csv Product Feed ProductFeed</Title>
99
<IsPackable>true</IsPackable>

src/Geta.Optimizely.ProductFeed.Google/Geta.Optimizely.ProductFeed.Google.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
<PropertyGroup>
44
<TargetFramework>net6.0</TargetFramework>
5-
<Version>3.0.1</Version>
6-
<PackageVersion>3.0.1</PackageVersion>
5+
<Version>3.0.2</Version>
6+
<PackageVersion>3.0.2</PackageVersion>
77
<PackageId>Geta.Optimizely.ProductFeed.Google</PackageId>
88
<Title>Geta Optimizely Google Product Feed ProductFeed</Title>
99
<IsPackable>true</IsPackable>

src/Geta.Optimizely.ProductFeed/Configuration/FeedDescriptor.cs

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,33 @@
33

44
using System;
55

6-
namespace Geta.Optimizely.ProductFeed.Configuration
6+
namespace Geta.Optimizely.ProductFeed.Configuration;
7+
8+
public class FeedDescriptor
79
{
8-
public class FeedDescriptor
10+
public FeedDescriptor(string name, string fileName, string mimeType)
911
{
10-
public FeedDescriptor(string name, string fileName, string mimeType)
11-
{
12-
Name = name;
13-
FileName = fileName;
14-
MimeType = mimeType;
15-
}
12+
Name = name;
13+
FileName = fileName;
14+
MimeType = mimeType;
15+
}
1616

17-
public string Name { get; set; }
17+
public string Name { get; set; }
1818

19-
public string FileName { get; set; }
19+
public string FileName { get; set; }
2020

21-
public string MimeType { get; set; }
21+
public string MimeType { get; set; }
2222

23-
public Type Exporter { get; set; }
23+
public Type Exporter { get; set; }
2424

25-
public Type Converter { get; set; }
25+
public Type Converter { get; set; }
2626

27-
public Type Filter { get; set; }
27+
public Type Filter { get; set; }
2828

29-
public Type SiteUrlBuilder { get; set; }
29+
public Type SiteUrlBuilder { get; set; }
3030

31-
public void SetSiteUrlBuilder<TBuilder>() where TBuilder : ISiteUrlBuilder
32-
{
33-
SiteUrlBuilder = typeof(TBuilder);
34-
}
31+
public void SetSiteUrlBuilder<TBuilder>() where TBuilder : ISiteUrlBuilder
32+
{
33+
SiteUrlBuilder = typeof(TBuilder);
3534
}
3635
}

src/Geta.Optimizely.ProductFeed/Configuration/ProductFeedOptions.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public class ProductFeedOptions<TEntity> : ProductFeedOptions
2727

2828
public Type EntityMapper { get; set; }
2929

30+
public TimeSpan CommandTimeout { get; set; } = TimeSpan.FromSeconds(30);
31+
3032
public void Add(FeedDescriptor feedDescriptor)
3133
{
3234
Descriptors.Add(feedDescriptor);

src/Geta.Optimizely.ProductFeed/Geta.Optimizely.ProductFeed.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
<PropertyGroup>
44
<TargetFramework>net6.0</TargetFramework>
5-
<Version>3.0.1</Version>
6-
<PackageVersion>3.0.1</PackageVersion>
5+
<Version>3.0.2</Version>
6+
<PackageVersion>3.0.2</PackageVersion>
77
<PackageId>Geta.Optimizely.ProductFeed</PackageId>
88
<Title>Geta Optimizely Product Feed ProductFeed</Title>
99
<IsPackable>true</IsPackable>
Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,33 @@
11
// Copyright (c) Geta Digital. All rights reserved.
22
// Licensed under Apache-2.0. See the LICENSE file in the project root for more information
33

4+
using System;
45
using Geta.Optimizely.ProductFeed.Models;
56
using Microsoft.EntityFrameworkCore;
67

78
// TODO: test namespace change
8-
namespace Geta.Optimizely.GoogleProductFeed.Repositories
9-
{
10-
public class FeedApplicationDbContext : DbContext
11-
{
12-
private readonly string _connectionString;
9+
namespace Geta.Optimizely.GoogleProductFeed.Repositories;
1310

14-
public FeedApplicationDbContext(string connectionString)
15-
{
16-
_connectionString = connectionString;
17-
}
11+
public sealed class FeedApplicationDbContext : DbContext
12+
{
13+
private readonly string _connectionString;
1814

19-
public FeedApplicationDbContext(DbContextOptions options) : base(options)
20-
{
21-
}
15+
public FeedApplicationDbContext(string connectionString, TimeSpan commandTimeout)
16+
{
17+
_connectionString = connectionString;
18+
Database.SetCommandTimeout(commandTimeout);
19+
}
2220

23-
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
24-
{
25-
if (optionsBuilder.IsConfigured) return;
21+
public FeedApplicationDbContext(DbContextOptions options) : base(options)
22+
{
23+
}
2624

27-
optionsBuilder.UseSqlServer(_connectionString);
28-
}
25+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
26+
{
27+
if (optionsBuilder.IsConfigured) return;
2928

30-
public DbSet<FeedEntity> FeedData { get; set; }
29+
optionsBuilder.UseSqlServer(_connectionString);
3130
}
31+
32+
public DbSet<FeedEntity> FeedData { get; set; }
3233
}

src/Geta.Optimizely.ProductFeed/Repositories/FeedRepository.cs

Lines changed: 73 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,75 +4,98 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Linq;
7+
using System.Threading;
8+
using System.Threading.Tasks;
79
using Geta.Optimizely.GoogleProductFeed.Repositories;
810
using Geta.Optimizely.ProductFeed.Configuration;
911
using Geta.Optimizely.ProductFeed.Models;
12+
using Microsoft.EntityFrameworkCore;
1013

11-
namespace Geta.Optimizely.ProductFeed.Repositories
14+
namespace Geta.Optimizely.ProductFeed.Repositories;
15+
16+
public class FeedRepository : IFeedRepository
1217
{
13-
public class FeedRepository : IFeedRepository
18+
private readonly FeedApplicationDbContext _applicationDbContext;
19+
private readonly IEnumerable<FeedDescriptor> _descriptors;
20+
21+
public FeedRepository(FeedApplicationDbContext applicationDbContext, IEnumerable<FeedDescriptor> descriptors)
1422
{
15-
private readonly FeedApplicationDbContext _applicationDbContext;
16-
private readonly IEnumerable<FeedDescriptor> _descriptors;
23+
_applicationDbContext = applicationDbContext;
24+
_descriptors = descriptors;
25+
}
1726

18-
public FeedRepository(FeedApplicationDbContext applicationDbContext, IEnumerable<FeedDescriptor> descriptors)
27+
public FeedEntity GetLatestFeed(Uri siteUri)
28+
{
29+
if (siteUri == null)
1930
{
20-
_applicationDbContext = applicationDbContext;
21-
_descriptors = descriptors;
31+
throw new ArgumentNullException(nameof(siteUri));
2232
}
2333

24-
public FeedEntity GetLatestFeed(Uri siteUri)
34+
// we need to do client-side eval because string.Equals with comparison is not supported
35+
var feedContent = _applicationDbContext
36+
.FeedData
37+
.ToList();
38+
39+
return feedContent.FirstOrDefault(f => f.Link.Equals(GetAbsoluteUrlWithoutQuery(siteUri).AbsoluteUri.TrimEnd('/'),
40+
StringComparison.InvariantCultureIgnoreCase));
41+
}
42+
43+
public void Save(ICollection<FeedEntity> feedData)
44+
{
45+
if (feedData == null)
2546
{
26-
if (siteUri == null)
27-
{
28-
throw new ArgumentNullException(nameof(siteUri));
29-
}
30-
31-
// we need to do client-side eval because string.Equals with comparison is not supported
32-
var feedContent = _applicationDbContext
33-
.FeedData
34-
.ToList();
35-
36-
return feedContent.FirstOrDefault(f => f.Link.Equals(GetAbsoluteUrlWithoutQuery(siteUri).AbsoluteUri.TrimEnd('/'),
37-
StringComparison.InvariantCultureIgnoreCase));
47+
return;
3848
}
3949

40-
public void Save(ICollection<FeedEntity> feedData)
50+
var feeds = _applicationDbContext.FeedData.ToList();
51+
52+
foreach (var data in feedData)
4153
{
42-
if (feedData == null)
43-
{
44-
return;
45-
}
46-
47-
var feeds = _applicationDbContext.FeedData.ToList();
48-
49-
foreach (var data in feedData)
50-
{
51-
var found = feeds.FirstOrDefault(f => f.Link.Equals(data.Link, StringComparison.InvariantCultureIgnoreCase));
52-
53-
if (found != null)
54-
{
55-
found.CreatedUtc = DateTime.UtcNow;
56-
found.FeedBytes = data.FeedBytes;
57-
}
58-
else
59-
{
60-
data.CreatedUtc = DateTime.UtcNow;
61-
_applicationDbContext.FeedData.Add(data);
62-
}
63-
64-
_applicationDbContext.SaveChanges();
65-
}
54+
PrepareFeedData(feeds, data);
55+
_applicationDbContext.SaveChanges();
6656
}
57+
}
6758

68-
public FeedDescriptor FindDescriptorByUri(Uri siteUri)
59+
public async Task SaveAsync(ICollection<FeedEntity> feedData, CancellationToken cancellationToken)
60+
{
61+
if (feedData == null)
6962
{
70-
var path = GetAbsoluteUrlWithoutQuery(siteUri).AbsolutePath.Trim('/');
63+
return;
64+
}
7165

72-
return _descriptors.FirstOrDefault(d => d.FileName.Trim('/').Equals(path, StringComparison.InvariantCultureIgnoreCase));
66+
var feeds = await AsyncEnumerable.ToListAsync(_applicationDbContext.FeedData, cancellationToken);
67+
foreach (var data in feedData)
68+
{
69+
PrepareFeedData(feeds, data);
70+
await _applicationDbContext.SaveChangesAsync(cancellationToken);
7371
}
72+
}
7473

75-
private Uri GetAbsoluteUrlWithoutQuery(Uri siteUri)
76-
=> new UriBuilder(siteUri) { Query = string.Empty }.Uri;
74+
private void PrepareFeedData(List<FeedEntity> feeds, FeedEntity data)
75+
{
76+
var found = feeds.FirstOrDefault(f => f.Link.Equals(data.Link, StringComparison.InvariantCultureIgnoreCase));
77+
78+
if (found != null)
79+
{
80+
found.CreatedUtc = DateTime.UtcNow;
81+
found.FeedBytes = data.FeedBytes;
82+
}
83+
else
84+
{
85+
data.CreatedUtc = DateTime.UtcNow;
86+
_applicationDbContext.FeedData.Add(data);
87+
}
88+
}
89+
90+
public FeedDescriptor FindDescriptorByUri(Uri siteUri)
91+
{
92+
var path = GetAbsoluteUrlWithoutQuery(siteUri).AbsolutePath.Trim('/');
93+
94+
return _descriptors.FirstOrDefault(d => d.FileName.Trim('/').Equals(path, StringComparison.InvariantCultureIgnoreCase));
95+
}
96+
97+
private Uri GetAbsoluteUrlWithoutQuery(Uri siteUri)
98+
{
99+
return new UriBuilder(siteUri) { Query = string.Empty }.Uri;
77100
}
78101
}

src/Geta.Optimizely.ProductFeed/Repositories/IFeedRepository.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,20 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using Geta.Optimizely.ProductFeed.Configuration;
79
using Geta.Optimizely.ProductFeed.Models;
810

9-
namespace Geta.Optimizely.ProductFeed.Repositories
11+
namespace Geta.Optimizely.ProductFeed.Repositories;
12+
13+
public interface IFeedRepository
1014
{
11-
public interface IFeedRepository
12-
{
13-
FeedEntity GetLatestFeed(Uri siteUri);
15+
FeedEntity GetLatestFeed(Uri siteUri);
16+
17+
void Save(ICollection<FeedEntity> feedData);
1418

15-
void Save(ICollection<FeedEntity> feedData);
19+
Task SaveAsync(ICollection<FeedEntity> feedData, CancellationToken cancellationToken);
1620

17-
FeedDescriptor FindDescriptorByUri(Uri siteUri);
18-
}
21+
FeedDescriptor FindDescriptorByUri(Uri siteUri);
1922
}

src/Geta.Optimizely.ProductFeed/ServiceCollectionExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public static IServiceCollection AddProductFeed<TEntity>(
3131
services.AddTransient(provider =>
3232
{
3333
var options = provider.GetRequiredService<IOptions<ProductFeedOptions<TEntity>>>();
34-
return new FeedApplicationDbContext(options.Value.ConnectionString);
34+
return new FeedApplicationDbContext(options.Value.ConnectionString, options.Value.CommandTimeout);
3535
});
3636

3737
services.AddTransient<FeedBuilderCreateJob>();

0 commit comments

Comments
 (0)