I'm using async / await methods in C#... my operations are to create databases on Azure Cosmos DB, the problem is when the code is runnnig, for any reason... the flow brakes without any issues apparently
can anyone help?
Task p= Run();
public async static Task Run()
{
.
.
.
await CreateDatabase(client)
}
private async static Task CreateDatabase(DocumentClient client)
{
var databaseDefinition = new Database { Id = "MyDB" };
var result = await client.CreateDatabaseAsync(databaseDefinition);
var database = result.Resource;
}
//In second line, the code brake when the debugging is operating
//==> var result = await client.CreateDatabaseAsync(databaseDefinition);
Related
I have a InMemory Cache method which I want to implement using Redis Cache, it uses the concept of Semaphore in the InMemory Cache, hence I have gone through many documentation's like the Redis documentation on Distributed Locking, and tried using different locking mechanisms in Redis such as RedLock.Net , RedLock-cs etc, but I haven't been able to completely go through with the technique, as even though I am able to recreate the method, but the running time for large number of processes for it in Redis is coming out to be huge.
The code that I am trying to recreate is as follows:
private readonly ConcurrentDictionary<string, Lazy<SemaphoreSlim>> _semaphores = new ConcurrentDictionary<string, Lazy<SemaphoreSlim>>();
public async ValueTask<TValue> GetMethod<TValue>(string key,Func<Task<TValue>> get,int time)
{
return await SemaphoreMethod(key, async() =>
{
var value = await get();
if(value != null)
cache.set(key,value,time);
return value;
});
}
private async ValueTask<TValue> SemaphoreMethod<TValue>(string key,Func<Task<TValue>> get)
{
if(cache.TryGetValue(key,out TValue result))
return result;
var semaphore = _semaphores.GetOrAdd(key,k => new Lazy<SemaphoreSlim>(() => new SemaphoreSlim(1,1))).Value;
await semaphore.WaitAsync();
TValue answer = default;
if(cache.TryGetValue(key,out TValue result2))
return result2;
answer = await get();
_semaphores.TryRemove(key,out _);
semaphore.Release();
return answer;
}
And the method which I run against it to check it's implementation and efficiency in comparison to InMemory Cache is as follows:
public async Task GetValueAsync_Tasks()
{
var callCount = 0;
async Task<string> Get()
{
Interlocked.Increment(ref callCount);
return "value";
}
const int count = 1000;
var valueTasks = new List<ValueTask<string>>(count);
for(var i=0;i<count;i++)
valueTask.Add(GetMethod("key",Get));
var tasks = valueTasks.Select(vt => vt.AsTask()).ToArray();
Task.WaitAll(tasks);
callCount.Should().Be(1);
}
One other thing that I am not able to understand that in which part of the test method, would the code run all the tasks created, i.e. in this one
valueTasks.Add(sut.GetValueAsync("key", FetchValue));
or in this one
Task.WaitAll(tasks);
I am using the StackExchange.Redis library, and Azure Cache for Redis for storing the respective data.
Has anyone had any success in setting up integration testing for web applications written in .NET 6 and EntityFramework Core 6, and using SQLite in-memory database? I am having issues with test setup/teardown, so tests which run fine in isolation, start randomly failing when running all tests together.
My test context is set up based on the Microsoft examples:
public class TestApplication : AutofacWebApplicationFactory<Startup>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureTestServices(services =>
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = FakeJwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = FakeJwtBearerDefaults.AuthenticationScheme;
}).AddFakeJwtBearer();
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(FakeJwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.Build();
});
var connectionString = new SqliteConnectionStringBuilder($"DataSource=file:{Guid.NewGuid()}?cache=shared&mode=memory");
var connection = new SqliteConnection(connectionString.ToString());
connection.Open();
var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<MyDbContext>));
if (descriptor != null)
{
services.Remove(descriptor);
}
services.AddDbContext<MyDbContext>(options =>
{
options.UseSqlite(connection);
});
var sp = services.BuildServiceProvider();
using var scope = sp.CreateScope();
var scopedServices = scope.ServiceProvider;
var db = scopedServices.GetRequiredService<MyDbContext>();
var logger = scopedServices.GetRequiredService<ILogger<TestApplication>>();
db.Database.EnsureDeleted();
db.Database.EnsureCreated();
try
{
logger.LogInformation("Initialising in-memory database with test data");
TestData.Initialise(db);
}
catch (Exception ex)
{
logger.LogError(ex, "An error occurred seeding the database with test messages. Error: {Message}", ex.Message);
}
});
}
}
which will be used in my test fixtures something like this:
public class WhenGettingPartners
{
[Fact]
public async Task ItShouldAcceptValidRequests()
{
await using var app = new TestApplication();
var client = app.CreateClient().WithRoles(Scopes.PartnerRead);
var result = await client.GetAsync("/Partners");
result.Should().BeSuccessful();
var data = await result.Content.ReadAsType<Partner[]>();
data.Should().NotBeEmpty();
}
[Fact]
public async Task ItShouldRejectUnauthorisedRequests()
{
await using var app = new TestApplication();
var client = app.CreateClient();
var result = await client.GetAsync("/Partners");
result.Should().HaveStatusCode(HttpStatusCode.Unauthorized);
}
}
If I select an individual test case and run it, it works fine; if I select the entire text fixture and run it, it works fine. But when I run the entire test project, then tests will fail randomly, usually when it tries to recreate the database and finds the tables already exist.
I've tried using xUnit's IClassFixture interface to share one instance of TestApplication across all tests in the fixture:
public abstract class ApiTestFixture : IClassFixture<TestApplication>
{
public ApiTestFixture(TestApplication application)
{
App = application;
}
public TestApplication App { get; }
}
public class WhenGettingClients : ApiTestFixture
{
public WhenGettingClients(TestApplication app) : base(app)
{
}
[Fact]
public async Task ItShouldAcceptValidRequests()
{
var client = App.CreateClient().WithRoles(Scopes.ClientRead);
var result = await client.GetAsync("/Clients");
result.Should().BeSuccessful();
var data = await result.Content.ReadAsType<Client[]>();
data.Should().HaveCount(2);
}
[Fact]
public async Task ItShouldRejectUnauthorisedRequests()
{
var client = App.CreateClient();
var result = await client.GetAsync("/Clients");
result.Should().HaveStatusCode(HttpStatusCode.Unauthorized);
}
}
but that fails in exactly the same way.
Update
I am developing using the Rider IDE from JetBrains; the same issue occurs if I run the tests in Visual Studio. However, I noticed that if I test with code coverage in Rider, then the tests all pass! Similarly, if I test with profiling in Rider, then the tests all pass; so I'm wondering if there's something more esoteric going on, that the code coverage runner somehow forces the tests to execute in a manner which is more deterministic or less likely to result in test pollution.
When I create a database I want to initialize it with a ton of data.
I have the following initialization service.
// This needs to be a top-level method because it's run on a background isolate
DatabaseConnection _backgroundConnection() {
// construct the database. You can also wrap the VmDatabase in a "LazyDatabase" if you need to run
// work before the database opens.
final database = VmDatabase.memory();
return DatabaseConnection.fromExecutor(database);
}
Future<void> _initDatabase(Map<String, dynamic> args) async {
var moorIsolate = await MoorIsolate.spawn(_backgroundConnection);
var connection = await moorIsolate.connect();
var db = BillingDatabase.connect(connection);
_initBillingSpecialties(db, args["specialties"]);
}
Future<void> _initBillingSpecialties(BillingDatabase db, String specialtiesJson) async {
var json = jsonDecode(specialtiesJson);
var jsonSpecialties = json["specialties"] as List<dynamic>;
var specialities = jsonSpecialties.map((s) =>
DbSpecialtiesCompanion(name: Value(s["specialty_name"]),
mohNumber: Value(s["moh_specialty"]))).toList();
return db.specialtyDao.saveAllSpecialties(specialities);
}
#injectable
class InitDbService {
Future<void> initDatabase() async {
WidgetsFlutterBinding.ensureInitialized();
var specialties = await rootBundle.loadString("lib/assets/billing_specialties.json");
compute(_initDatabase, {"specialties": specialties});
//initDbSync(specialties);
}
Future<void> initDbSync(String specialtiesJson) async {
var json = jsonDecode(specialtiesJson);
var jsonSpecialties = json["specialties"] as List<dynamic>;
var specialities = jsonSpecialties.map((s) =>
DbSpecialtiesCompanion(name: Value(s["specialty_name"]),
mohNumber: Value(s["moh_specialty"]))).toList();
var dao = GetIt.instance.get<SpecialtyDao>();
return dao.saveAllSpecialties(specialities);
}
}
initDbSync runs and inserts just fine. While db.specialtyDao.saveAllSpecialties(specialities); never actually exectues any SQL. I have it printing log statements for the moment so I can see what it's doing.
Update: I found out that VmDatabase.memory(logStatements: true); was needed to see the SQL. I can see it printing the statements.
I'm running on a simulator so I can look at the raw db file. And there's nothing there. When I query in the app there's also nothing there.
So what's not really clear in the documentation is that VmDatabase.memory(); opens up a new database in memory. Not takes the database from memory.
You want to take your reference to the file that you pass in the constructor, and use
VmDatabase(File(dbFile));
then it will actually run on your sql.
How can I get count of connections in specific SignalR Core group?
Something like that:
this.Clients.Group("Something").Count();
It would be also good if SendAsync would return how many clients send message:
var count = await this.Clients.Client(this.Context.ConnectionId).SendAsync("msg", msg);
I need this to determine if group is empty. Data should be correct if user disconnects from SignalR Core with force (unplug net cable)...
You can use the OnConnected and OnDisconnected Events and save the connection / connectionIds.
I use something like this with additional informations:
internal static ConcurrentDictionary<string, ConnectionInfos> Users = new ConcurrentDictionary<string, ConnectionInfos>();
public override async Task OnConnectedAsync()
{
var connId = Context.ConnectionId;
if (!Users.Keys.Any(x => x == connId))
{
Users.TryAdd(connId, new ConnectionInfos { /*...*/});
}
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception exception)
{
var id = Context.ConnectionId;
if (Users.TryRemove(id, out ConnectionInfos ci))
{
//Connection removed
}
await base.OnDisconnectedAsync(exception);
}
There are two type of constructors I can call to initialise the Sqlite connection. I know SQLiteAsyncConnection is to create an async method when execute the sql statement whereas SQLiteConnection is for normal method.
If I have a method like below:
public object InsertVeggie(string name)
{
lock (locker) {
var sql = "Some query ?";
var result = database.Query<Model>(sql, name);
return result;
}
}
If I have an async method:
public async Task<Model> GetModel (string name)
{
var data = InsertVeggie(name);
await ProcessVeggie(data);
return data;
}
Calling method :
Task.Run (async () =>
{
var result1 = await GetModel("124");
});
Task.Run (async () =>
{
var result2 = await GetModel("335");
});
If I use SQLiteConnection instead of SQLiteAsyncConnection, will there be an issue or have to change the InsertVeggie to Async method as well.
As you say, SQLiteAsyncConnection exposes asynchronous methods so you would typically consume them from your own async methods.
Your InsertVeggie method would change to:
public async Task<object> InsertVeggie(string name)
{
var sql = "Some query ?";
var result = await database.QueryAsync<Model>(sql, name);
return result;
}
(note you no longer need the lock), and you would consume it as:
var data = await InsertVeggie(name);