How to globally change the command timeout using ServiceStack.OrmLite - servicestack

I have a reporting-based website using ServiceStack and OrmLite, using a SQL Server back-end. Due to the duration of some of the reports, I'd like to either globally, or selectively (via Service-derived class or some attribute) make queries that run reports have a longer CommandTimeout. I'd like to keep using the existing code to query data for the reports (Db.Select, Db.SqlList calls), so I won't have to write boiler-plate code in each reporting class & method.
I've tried using the AlwaysUseCommand, but that requires declaring a single command that has an open connection. I don't see how I can do that without opening the connection in my AppHost.Configure method and never closing it. It'd be nicer if it were a function pointer, but alas.
I've also looked at overriding the Db property of Service, but that just returns an open IDbConnection without letting me override command created.
It seems like my last option is to create a custom DbConnection class, like the MiniProfiler's ProfiledDbConnection, but I'd have to implement a dozen abstract methods. It seems like overkill in order to set one property on a DbCommand.
So, in ServiceStack.OrmLite, how do I globally modify the CommandTimeout of DbCommands that are created?

You can change the CommandTimeout globally with:
OrmLiteConfig.CommandTimeout = NewTimeoutInSeconds;
Scoped Timeout
You can also specify a Timeout for a particular db connection with:
using (var db = dbFactory.OpenDbConnection())
{
db.SetCommandTimeout(NewTimeoutInSeconds);
}

Related

How to get query string in case CQLStatement,QueryState and QueryOptions is given

Cassandra has org.apache.cassandra.cql3.QueryHandler interface which provide apis to handle external queries from client.
Below api which handles prepared statment:
public ResultMessage processPrepared(CQLStatement statement, QueryState state, QueryOptions options) throws RequestExecutionException, RequestValidationException;
I want to log queryString and value passed to it, in case CQLStatement,QueryState and QueryOptions is given . How can i get it?
I Believe a person who has worked on cassandra code can help me out in this.
This would be very difficult in 2.1. With newer versions where for logging they needed this they just recreate it as well as possible. You can see how in the ReadCommand implementations, theres a name() or toCQLString() used in things like slow query logging. You could backport this and the 2 implementations of appendCQLWhereClause for ability to do similar and then build one for modification statement.
in getPrepared() you can get the rawCQLStatement from the ParsedStatement.Prepared and stash it in the thread local.
You may want to alternatively consider using a custom implementation of tracing (example) or using triggers and building a mutation logger.
Do the following:
create a class that would implement the QueryHandler interface and make Cassandra aware of it
in that class you can maintain a list of the queries (add to this list when prepare method is being called) and the current query that you will get from the list when getPrepared it's called; you can get it from the list using the MD5Digest id
when processPrepared is called you can replace the ? in the query string with the values in the QueryOptions options.getValues().
HTH

Error 500 after connecting to Redis in Jmeter

I have a question about Groovy scripting in Jmeter.
I have created a function in Groovy that connects to Redis DB, and the function works as expected.
Afterwards, when from "main" I try to get data, it says that he is not familiar with get from Redis.
My purpose is to create the first function that connects to Redis, the second one that creates Redis key, and the third one to get data using the Redis key.
in the "main" I call connect and it works, but the third one does not work. Is it because the connection is closed?
Not seeing your code it is hard to guess what is wrong, according to the error message jedis variable is not defined in the scope, you are trying to access it. you can try defining it globally like:
def jedis = null; // make "jedis" variable available to all methods
void connect() {
jedis = new Jedis(vars.get('Redis_IP', vars.get('Redis_Port') as int)
}
void somethingElse () {
if (jedis != null) {
log.info(jedis.ping())
}
}
A couple of points to consider:
Don't inline JMeter Variables or Functions into script body, it makes compilation caching feature aimpossible so the overall performance of your code will be lower. Also variables might resolve into something causing script interpretation failure or unexpected behaviour. Either use "Parameters" section or go for code-based equivalents as in my above demo
It is recommended to use JMeter built-in features (or plugins) where possible as even well-behaved Groovy script doesn't perform that fast as "normal" Java code. Check out if Redis Data Set is matching your use case and if it does - simply install it using JMeter Plugins Manager and start using instead of struggling with Groovy.
See JMeter’s Redis Data Set - An Introduction article for step-by-step instructions on the plugin installation and usage

mongodb / node - ignore certain object properties

Is there a way to tell MongoClient that there are some properties I don't want to store? For example, I have some properties that are cyclic dependencies which fail to serialize - this causes a few problems. I'd rather not have to set them to null before I save them every time, then re-instate those variables when the insert has finished.
One way to do this is with a little help from the omit method of the underscore (or lodash) library. That will cleanly create a copy of your object without the problematic properties.
var objectToInsert = _.omit(fullObject, 'badField1', 'badField2');
collection.insert(objectToInsert, callback);
Another way to go is to use Mongoose which lets you define schemas for your collections so that only those fields in the schema get included when saved.

How does Database.SetInitializer actually work? (EF code-first create database and apply migrations using several connection strings)

I am trying to write a method to create a database and run migrations on it, given the connection string.
I need the multiple connections because I record an audit log in a separate database.
I get the connection strings out of app.config using code like
ConfigurationManager.ConnectionStrings["Master"].ConnectionString;
The code works with the first connection string defined in my app.config but not others, which leads me to think that somehow it is getting the connection string from app.config in some manner I don't know.
My code to create the database if it does not exist is
private static Context MyCreateContext(string ConnectionString)
{
// put the connection string where the factory method can get it
AppDomain.CurrentDomain.SetData("ConnectionString", ConnectionString );
var factory = new ContextFactory();
// I know I need this line - but I cant see how what follows actually uses it
Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context,DataLayer.Migrations.Configuration>());
var context = factory.Create();
context.Database.CreateIfNotExists();
return context
}
The code in the Migrations.Configuration is
Public sealed class Configuration : DbMigrationsConfiguration<DataLayer.Context>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
}
The context factory code is
public class ContextFactory : IDbContextFactory<Context>
{
public Context Create()
{
var s = (string)AppDomain.CurrentDomain.GetData("ConnectionString");
return new Context(s);
}
}
Thus I am setting the connection string before creating the context.
Where can I be going wrong, given that the connection strings are all the same except the database name, and the migration code runs with one connection string, but doesnt run with others?
I wonder if my problem is to do with understanding how How does Database.SetInitializer actually works. I am guessing something about reflection or generics. How do i make the call to SetInitializer tie tie to my actual context?
I have tried the following code but the migrations do not run
private static Context MyCreateContext(string ConnectionString)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context, DataLayer.Migrations.Configuration>());
var context = new Context(ConnectionString);
context.Database.CreateIfNotExists();
}
This question appears to be related
UPDATE:
I can get the migrations working if I refer to the connection string using
public MyContext() : base("MyContextConnection") - which points to in the config
I was also able to get migrations working on using different instances of the context, if I created a ContextFactory class and passed the connection to it by referencing a global. ( See my answer to the related question link )
Now I am wondering why it has to be so hard.
I'm not sure exactly as to what the problems are you facing, but let me try
The easiest way to provide connection - and be sure it works that way...
1) Use your 'DbContext' class name - and define a connection in the app.config (or web.config). That's easiest, you should have a connection there that matches your context class name,
2) If you put it into the DbContext via constructor - then be consistent and use that one. I'd also suggest to 'read' from config connections - and again name it 'the same' as your context class (use the connection 'name', not the actual string),
3) if none is present - EF/CF makes the 'default' one - based on your provider - and your context's class name - which usually isn't what you want,
You shouldn't customize with initializers for that reason -
initializers should be agnostic and serve other purpose - setup
connection in the .config - or directly on your DbContext
Also check this Entity Framework Code First - How do I tell my app to NOW use the production database once development is complete instead of creating a local db?
Always check 'where your data' goes - before doing anything.
For how the initializer actually works - check this other post of mine, I made a thorough example
How to create initializer to create and migrate mysql database?
Notes: (from the comments)
Connection shouldn't be very dynamic - config is the right place for it to be, unless you have a good reason.
Constructor should work fine too.
CreateDbIfNotExists doesn't work well together with the 'migration' initializer. You can just use the MigrateDatabaseToLatestVersion initializer. Don't 'mix' it
Or - put something like public MyContext() : base("MyContextConnection") - which points to <connectionStrings> in the config
To point to connection - just use its 'name' and put that into constructor.
Or use somehting like ConfigurationManager.ConnectionStrings["CommentsContext"].ConnectionString
Regarding entertaining 'multiple databases' with migrations (local and remote from one app) - not exactly related - but this link - Migration not working as I wish... Asp.net EntityFramework
Update:
(further discussion here - Is adding a class that inherits from something a violation of the solid principles if it changes the behavior of code?)
It is getting interesting here. I did manage to reproduce the problems you're facing actually. Here is a short breakdown on what I think it's happening:
First, this worked 'happily':
Database.SetInitializer(new CreateAndMigrateDatabaseInitializer<MyContext, MyProject.Migrations.Configuration>());
for (var flip = false; true; flip = !flip)
{
using (var db = new MyContext(flip ? "Name=MyContext" : "Name=OtherContext"))
{
// insert some records...
db.SaveChanges();
}
}
(I used custom initializer from my other post, which controls migration/creation 'manually')
That worked fine w/o an Initializer. Once I switched that on, I ran into some curious problems.
I deleted Db-s (two, for each connection). I expected to either not work, or create one db, then another in the next pass (like it did, w/o migrations, just 'Create' initializer).
What happened, to my surprise - is it actually created both databases on the first
pass ??
Then, being a curious person:), I put breakpoints on the MyContext ctor, and debugged through the migrator/initializer. Again empty/no db-s etc.
It created first instance on my call within the flip. Then on the first access to 'model', it invoked the initializer. Migrator took over (having had no db-s). During the migrator.Update(); it actually constructs the MyContext (I'm guessing via generic param in Configuration) - and calls the 'default' empty ctor. That had the 'other connection/name' by default - and creates the other Db all as well.
So, I think this explains what you're experiencing. And why you had to create the 'Factory' to support the Context creation. That seems to be the only way. And setting some 'AppDomain' wide 'connection string' (which you did well actually) which isn't 'overriden' by default ctor call.
Solution that I see is - you just need to run everything through factory - and 'flip' connections in there (no need for static connection, as long as your factory is a singleton.
You can supply a configuration in the MigrateDatabaseToLatestVersion constructor.
If you set the initializer in the DbContext you can also pass a 'true' to use the current connection string.

Axis SecureSocketFactory - Setting the constructor attributes

I have a customer SecureSocketFactory set to be used by Axis when making an https connection using the following property:
AxisProperties.setProperty("axis.socketSecureFactory",
"com.metavante.csp.model.manager.mobilepayments.MonitiseSSLSocketFactory");
When this class is instantiated by Axis, the constructor with a Hashtable (attributes) is called. I see the timeout attribute is set in this table. Is there anyway to set more values in this?
I would like to be able to configure the Socket Factory on a per-instance scenario instead of globally by using static or system properties.
Edit: I found out these attributes are actually the HttpSender (BasicHandler) options. I still am unable to set these dynamically though.
I figured out a way around the problem. In my code where I wanted to set the property I use:
serviceLocator.getEngine().setOption(USE_CERT_PROPERTY, new Boolean(true));
where getEngine returns the AxisEngine in use. Then in the socket factory I can:
Boolean useSMS = (Boolean) MessageContext.getCurrentContext().getProperty(OtherClass.USE_CERT_PROPERTY);
I could set the object to whatever, maybe I'll go with the certificate name I needed. Hope this helps someone.
You can retrieve the SocketFactory instance and then change or add attributes, if you are interested in modify SocketFactory behavior. But if you do this, you also should inject the HashTable attribute (with the timeout). I think there is not a final and pretty solution.
AxisProperties.setProperty("org.apache.axis.components.net.SecureSocketFactory", MyAxisSocketFactory.class.getName());
MyAxisSocketFactory factory = (MyAxisSocketFactory) SocketFactoryFactory.getFactory("https", myHashTableParams);
factory.setMyStuff();
After this code, the instance of SocketFactory will be created and configured, and ready to use in web services, or whatever ^_^

Resources