.NET Ignite cache expiry policy not working - outputcache

I am trying to set a global expiring policy to a Ignite cache but it doesn't work, all the entries are still there even after the timeout value.
This is how I am implementing it:
var igniteCache = this.igniteInstance.GetOrCreateCache<string, object>(configuraton);
var expiringTime = TimeSpan.FromSeconds(100);
igniteCache.WithExpiryPolicy(new ExpiryPolicy(expiringTime, expiringTime, expiringTime));
igniteCache.Put(key, value);
What am I doing wrong?

WithExpiryPolicy returns a new cache instance, you should use it to insert entries with expiration:
var igniteCacheExpiry = igniteCache.WithExpiryPolicy(new ExpiryPolicy(expiringTime, expiringTime, expiringTime));
igniteCacheExpiry.Put(key, value)

Related

How to remove old data in redis when updating data?

I'm setting data in redis, but I update that data every minute, and I need redis to replace the old data with the new updated one. I am very confused as to how I might be able to achieve that. I tried to use client.expire('key', 60), but that doesn't seem to work. Below is my code. Any help would be appreciated. Thanks in advance.
var redis = require("redis"),
client = redis.createClient();
const { promisify } = require("util");
const setAsync = promisify(client.set).bind(client);
async function run(){
//do something
const success = await setAsync('mykey', list);
console.log({success});
client.expire('mykey', 59);
}
It seems like the key will be deleted (or more precisely, marked for deletion) 59 seconds after calling client.expire, but there are 2 things you need to be aware of:
If you call the EXPIRE command on a key that already have a TTL, it'll override the pervious TTL.
The expiration timeout is cleared once the value of the key is overwritten (using SET, DEL, etc.).
BTW, in case you're updating the exact same key, the data will be overwritten anyway.. for example:
await setAsync('key', 'value1'); // set 'key' to 'value1'
await setAsync('key', 'value2'); // override 'key' to 'value2'
await getAsync('key'); // 'value2'
Also, instead of running two commands, one for setting the value and one for setting the TTL, you can use the EX option like that:
setAsync('key', 'value', 'EX', 60); // set `key` to `value` with TTL of 60 seconds

Redlock.net can't aquire lock

Using:
StackExchange.Redis v1.1.608.0
RedLock.net v1.7.4.0
This code always returns false after 250-600ms:
var eps = new [] { new DnsEndPoint("localhost", 6379) };
var lf = new RedisLockFactory(eps);
var resource = "the-thing-we-are-locking-on";
var expiry = TimeSpan.FromSeconds(30);
using (var redisLock = lf.Create(resource, expiry))
{
Response.Write("Lock acquired: " + redisLock.IsAcquired);
}
I'm struggling to work out why, as I'm able to cache things in Redis just fine with StackExchange.Redis connection string localhost,allowAdmin=true.
In the Redis console I can see a client is being connected, but that's as far as it gets.
I've added a firewall rule for port 6379 but nothing changed.
Any ideas on my the lock can never be acquired?
Found the cause of the issue. I'm using MSOpenTech Redis server v3.2.100:
https://github.com/MSOpenTech/redis/releases
Rolling back to v3.0.500 appears to fix the issue. Not ideal, but in testing environment should be OK for now.

RavenDB fails with ConcurrencyException when using new transaction

This code always fails with a ConcurrencyException:
[Test]
public void EventOrderingCode_Fails_WithConcurrencyException()
{
Guid id = Guid.NewGuid();
using (var scope1 = new TransactionScope())
using (var session = DataAccess.NewOpenSession)
{
session.Advanced.UseOptimisticConcurrency = true;
session.Advanced.AllowNonAuthoritativeInformation = false;
var ent1 = new CTEntity
{
Id = id,
Name = "George"
};
using (var scope2 = new TransactionScope(TransactionScopeOption.RequiresNew))
{
session.Store(ent1);
session.SaveChanges();
scope2.Complete();
}
var ent2 = session.Load<CTEntity>(id);
ent2.Name = "Gina";
session.SaveChanges();
scope1.Complete();
}
}
It fails at the last session.SaveChanges. Stating that it is using a NonCurrent etag. If I use Required instead of RequiresNew for scope2 - i.e. using the same Transaction. It works.
Now, since I load the entity (ent2) it should be using the newest Etag unless this is some cached value attached to scope1 that I am using (but I have disabled Caching). So I do not understand why this fails.
I really need this setup. In the production code the outer TransactionScope is created by NServiceBus, and the inner is for controlling an aspect of event ordering. It cannot be the same Transaction.
And I need the optimistic concurrency too - if other threads uses the entity at the same time.
BTW: This is using Raven 2.0.3.0
Since no one else have answered, I had better give it a go myself.
It turns out this was a human error. Due to a bad configuration of our IOC container the DataAccess.NewOpenSession gave me the same Session all the time (across other tests). In other words Raven works as expected :)
Before I found out about this I also experimented with using TransactionScopeOption.Suppress instead of RequiresNew. That also worked. Then I just had to make sure that whatever I did in the suppressed scope could not fail. Which was a valid option in my case.

Booksleeve setting expiration on multiple key/values

Unless I am missing something, I don't see a Multiple Set/Add overload that allows you to set multiple keys with an expiration.
var conn = new RedisConnection("server");
Dictionary<string,string> keyvals;
conn.Strings.Set(0,keyvals,expiration);
or even doing it with multiple operations
conn.Strings.Set(0,keyvals);
conn.Expire(keyvals.Keys,expiration);
No such redis operation exists - expire is not varadic. However, since the api is pipelined, just call the method multiple times. If you want to ensure absolute best performance, you can suspend eager socket flushing while you do this:
conn.SuspendFlush();
try {
foreach(...)
conn.Keys.Expire(...);
} finally {
conn.ResumeFlush();
}
Here is my approach:
var expireTime = ...
var batchOp = redisCache.CreateBatch();
foreach (...) {
batchOp.StringSetAsync(key, value, expireTime);
}
batchOp.Execute();

Multiple sessions with Fluent NHibernate and Ninject

I am working on setting up a multi-tenant, seperate database application and have made some good progress from reading this post below on stackoverflow.
Multitenancy with Fluent nHibernate and Ninject. One Database per Tenant
I see two sessions being setup. One is the 'master' session that will be used to get the tenant information and then the tenant session which is specific to the subdomain. I have the app switching nicely to the specified database based on domain and have questions on how to setup the 'master' database session and how to use it.
I tried registering a new session specifically for the master session be get an error regarding having already registered an ISession.
I'm new to nHibernate and not sure the best route to take on this.
NinjectWebCommon.cs
kernel.Bind<WebApplication1.ISessionSource>().To<NHibernateTenantSessionSource>().InSingletonScope();
kernel.Bind<ISession>().ToMethod(c => c.Kernel.Get<WebApplication1.ISessionSource>().CreateSession());
kernel.Bind<ITenantAccessor>().To<DefaultTenantAccessor>();
ITenantAccessor.cs
public Tenant GetCurrentTenant()
{
var host = HttpContext.Current.Request.Url != null ? HttpContext.Current.Request.Url.Host : string.Empty;
var pattern = ConfigurationManager.AppSettings["UrlRegex"];
var regex = new Regex(pattern);
var match = regex.Match(host);
var subdomain = match.Success ? match.Groups[1].Value.ToLowerInvariant() : string.Empty;
Tenant tenant = null;
if (subdomain != null)
{
// Get Tenant info from Master DB.
// Look up needs to be cached
DomainModel.Master.Tenants tenantInfo;
using (ISession session = new NHibernateMasterSessionSource().CreateSession())
{
tenantInfo = session.CreateCriteria<DomainModel.Master.Tenants>()
.Add(Restrictions.Eq("SubDomain", subdomain))
.UniqueResult<WebApplication1.DomainModel.Master.Tenants>();
}
var connectionString = string.Format(ConfigurationManager.AppSettings["TenanatsDataConnectionStringFormat"],
tenantInfo.DbName, tenantInfo.DbUsername, tenantInfo.DbPassword);
tenant = new Tenant();
tenant.Name = subdomain;
tenant.ConnectionString = connectionString;
}
return tenant;
}
Thanks for you time on this.
Add another session binding and add some condition. E.g.
kernel
.Bind<ISession>()
.ToMethod(c => c.Kernel.Get<NHibernateMasterSessionSource>().CreateSession())
.WhenInjectedInto<TenantEvaluationService>();