c# caching cassandra datastax opscenter

c# - Problema preparado de caché de sentencias en el controlador de Cassandra Csharp



caching datastax (2)

Creo que he encontrado un error con la lógica de cómo una declaración preparada se guarda en caché en StatementFactory en el controlador csharp de Cassandra (versión 2.7.3). Aquí está el caso de uso.

Guid key = Guid.NewGuid(); // your key ISession session_foo = new Session("foo"); //This is pseudo code ISession session_bar = new Session("bar"); var foo_mapper = new Mapper(session_foo); //table foo_bar var bar_mapper = new Mapper(session_bar); //table foo_bar await Task.WhenAll( foo_mapper.DeleteAsync<Foo>("WHERE id = ?", key), bar_mapper.DeleteAsync<Bar>("WHERE id = ?", key));

Hemos encontrado que después de ejecutar esta eliminación, solo la primera solicitud está teniendo éxito. Después de bucear en el código fuente de StatementFactory

public Task<Statement> GetStatementAsync(ISession session, Cql cql) { if (cql.QueryOptions.NoPrepare) { // Use a SimpleStatement if we''re not supposed to prepare Statement statement = new SimpleStatement(cql.Statement, cql.Arguments); SetStatementProperties(statement, cql); return TaskHelper.ToTask(statement); } return _statementCache .GetOrAdd(cql.Statement, session.PrepareAsync) .Continue(t => { if (_statementCache.Count > MaxPreparedStatementsThreshold) { Logger.Warning(String.Format("The prepared statement cache contains {0} queries. Use parameter markers for queries. You can configure this warning threshold using MappingConfiguration.SetMaxStatementPreparedThreshold() method.", _statementCache.Count)); } Statement boundStatement = t.Result.Bind(cql.Arguments); SetStatementProperties(boundStatement, cql); return boundStatement; }); }

Puede ver que la memoria caché solo usa la instrucción cql. En nuestro caso, tenemos los mismos nombres de tablas en diferentes espacios de claves (también conocidas como sesiones). Nuestra declaración de cql en ambas consultas tiene el mismo aspecto. es decir, ELIMINAR DE foo_bar WHERE id =? .

Si tuviera que adivinar, diría que una solución simple sería combinar la declaración cql y el espacio de claves juntos como la clave de caché.

¿Alguien más se ha encontrado con este problema antes?


Como una solución simple, me estoy saltando el caché mediante el uso de DoNotPrepare

await _mapper.DeleteAsync<Foo>(Cql.New("WHERE id = ?", key).WithOptions(opt => opt.DoNotPrepare()));

También encontré un problema abierto con Datastax


Hay un ticket abierto para corregir este comportamiento .

Como solución MappingConfiguration , puede usar instancias de MappingConfiguration diferentes al crear el Mapper :

ISession session1 = cluster.Connect("ks1"); ISession session2 = cluster.Connect("ks2"); IMapper mapper1 = new Mapper(session1, new MappingConfiguration()); IMapper mapper2 = new Mapper(session2, new MappingConfiguration());

O bien, puede reutilizar una sola instancia de ISession y calificar completamente sus consultas para incluir el espacio de claves.

MappingConfiguration.Global.Define( new Map<Foo>() .TableName("foo") .KeyspaceName("ks1"), new Map<Bar>() .TableName("bar") .KeyspaceName("ks2")); ISession session = cluster.Connect(); IMapper mapper = new Mapper(session);