How to make Symfony2 DIC to call Doctrine\ORM\Configuration#setHydrationCacheImpl() - caching

As of newer version of Doctrine2, I know there is Doctrine\ORM\Configuration#setHydrationCacheImpl()
to pass such as MemcacheCache, etc.
But how can it be done in container?
I'm using two entity_manager: named "default" and "other".
I first tried defining hydration_cache into config.yml like
doctrine:
orm:
default_entity_manager: default
...
entity_managers:
default:
...
metadata_cache_driver:
type: service
id: memcache_driver
...
hydration_cache_driver:
type: service
id: memcache_driver
...
other:
...
note: where memcache_driver is defined by me, instanceof Doctrine\Common\Cache\MemcacheCache
then I got Unrecognized options "hydration_cache_driver" under "doctrine.orm.entity_managers.default".
I also tried to directly tweak container in AppKernel#buildContainer,
but there's no instances of \Doctrine\ORM\Configuration defined as service,
so I couldn't retrieve the Configuration instance.
Any suggestions are welcome.
EDIT:
I'm sure that there is feature for caching hydrated object is re-implemented as of Doctrine 2.2.2.
http://www.doctrine-project.org/jira/browse/DDC-1766
https://github.com/doctrine/doctrine2/blob/2.2.2/tests/Doctrine/Tests/ORM/Functional/HydrationCacheTest.php?source=c
For other simple services, I can easily add methods to call by overwriting whole definitions like
service1:
...
calls:
[method calls]
but for the entity_manager, I'm not sure how to add method calls to them.
So my question in other words, how to configure orm at lower level like without using semantic configuration?

In my case, as hydration cache is hardly used,
so I decided this time to call Query#setHydrationCacheProfile just before each query is executed.
...
$query = $queryBuilder->getQuery();
$cache = $this->container->get('...'); //instanceof MemcacheCache
$query->setHydrationCacheProfile(new CacheProfile(null, null $cache));
$query->execute();
...

There is no such option "hydration_cache_driver", you should use "result_cache_driver" to achieve that.
From Doctrine 2.1, Doctrine can cache results of the queries, but it doesn't cache objects after hydration.
Look at doc about doctrine configuration:
http://symfony.com/doc/master/reference/configuration/doctrine.html

Related

How to optionally apply environment configuration?

I want to optionally apply a VPC configuration based on whether an environment variable is set.
Something like this:
custom:
vpc:
securityGroupIds:
- ...
subnetIds:
- ...
functions:
main:
...
vpc: !If
- ${env:USE_VPC}
- ${self:custom.vpc}
- ~
I'd also like to do similar for alerts (optionally add emails to receive alerts) and other fields too.
How can this be done?
I've tried the above configuration and a variety of others but just receive various different errors
For example:
Configuration error:
at 'functions.main.vpc': must have required property 'securityGroupIds'
at 'functions.main.vpc': must have required property 'subnetIds'
at 'functions.main.vpc': unrecognized property 'Fn::If'
Currently, the best way to achieve such behavior is to use JS/TS-based configuration instead of YAML. With TS/JS, you get full power of a programming language to shape your configuration however you want, including use of such conditional checks to exclude certain parts of the configuration. It's not documented too well, but you can use this as a starting point: https://github.com/serverless/examples/tree/v3/legacy/aws-nodejs-typescript
In general, you can do whatever you want, as long as you export a valid object (or a promise that resolves to a valid object) with serverless configuration.

Applying a dependency to a service in icinga2

We are using icinga2 for monitoring. We have a lot service checks which are applied dynamically through apply rules. Additionally, these are services applied to a hashmap of database instances which are on various hosts. The long and the short of it is that our service names are determined dynamically so one might be, for example HOST!DBNAME-svcvheck.
So the scenario is that most of these services depend on a database is up, e.g., `HOST!DBNAME-tnsping". Unfortunately, the documentation examples are fairly simple and don't include dynamically creating a parent service reference. What I think I want to do is something like this:
apply Dependency "db-connectivity" to Service {
parent_service_name = "$host.name$!$service.vars.envname$-tnsping"
# also tried variants of this, e.g.
# parent_service_name = host.name + "!" + service.vars.envname + "-tnsping"
child_service_name = service.name
child_host_name = host.name
disable_checks = true
assign where "oracle-db-svc" in service.templates
}
The host doesn't really matter in my case because the dependencies are only the services but the child_host_name is a required field.
No matter what I do I can't seem to get it to recognize the parent service. For example:
Error: Dependency 'scan-szepdb041x.myhost.org!UAT2-beqfilelast!db-connectivity' references a parent host/service which doesn't exist.
The rules for referencing other object variables while applying a Dependency seem a bit different from applying a Service.
Does anyone have any ideas or examples of dynamically apply service dependencies to services which were generated dynamically?
you probably have to loop over existing hosts and see if they match. Then you define dependency inside of a loop.
I had a similar example for dynamically generating disk checks. If i find it, i'll post it here in a few days.
Not sure if that is possible with dependencies, but I'll see.
edit: see if somethig like that will be enough to get you started:
for (server in get_objects(Host)) {
if (match("somename*", server.name)) {
apply Dependency "db-connectivity" + server.name to Service use (server) {
parent_service_name = server.name + service.vars.envvname + "-tnsping"
child_service_name = service.name
child_host_name = host.name
disable_checks = true
assign where "oracle-db-svc" in service.templates
}
}
}

Conditional routes and bot name in Lita

I am trying to develop a simple Lita chat bot with more flexible command routing.
There are a couple of issues I am having difficulties with.
1. Conditional routing
How can I use config values before or inside route definitions?
For example, instead of this definition that needs a "run" prefix:
route(/^\s*run\s+(\S*)\s*(.*)$/, :cmd, command: true)
I would like to use something like this, with a flexible, config-based prefix:
route(/^\s*#{config.prefix}\s+(\S*)\s*(.*)$/, :cmd, command: true)
Which fails. So I also tried something like this:
if config.use_prefix
route(/^\s*run\s+(\S*)\s*(.*)$/, :cmd, command: true)
else
route(/^\s*(\S*)\s*(.*)$/, :cmd, command: true)
end
Which also fails with a not very helpful error.
In both cases, I defined the proper config key with config :prefix and config :use_prefix.
2. Showing the bot name in the help
I know there is a robot.name property available for me inside the executed command, but I was unable to use it inside of the help string. I was trying to achieve something like this:
route(/^\s*run\s+(\S*)\s*(.*)$/, :cmd, command: true, help: {
"run SCRIPT" => "run the specified SCRIPT. use `#{robot.name} run list` for a list of available scripts."
})
but it just printed something unexpected.
Any help is appreciated.
The issue is that you're confusing the config class method and the config instance method. config at the class level (code in the class body but not inside an instance method definition) defines a new configuration attribute for the plugin. config at the instance level (inside an instance method or in an inline callback provided to route using a block) accesses the values of the plugin's own configuration at runtime.
In the current version of Lita, there isn't a pretty way to use runtime configuration in class-level definitions like chat routes. The workaround I've used myself is to register an event listener for the :loaded event, which triggers when the Lita::Robot has been initialized. At this point, configuration has been finalized, and you can use it to define more routes.
For example:
class MyHandler < Lita::Handler
on :loaded, :define_dynamic_routes
def define_dynamic_routes(payload)
if config.some_setting
self.class.route(/foo/, :callback)
else
self.class.route(/bar/, :callback)
end
end
end
You can look at the code for lita-karma for a more detailed example, as it uses this pattern.
The next major version of Lita is going to include an overhaul to the plugin system which will make this pattern much easier. For now, this is what I'd recommend, though.

Best strategy to cache expensive web service call in Grails

I have a simple Grails application that needs to make a periodic call to an external web service several times during a user's session (while the use the interface).
I'd like to cache this web service response, but the results from the service change about every few days, so I'd like to cache it for a short time (perhaps daily refreshes).
The Grails cache plugin doesn't appear to support "time to live" implementations so I've been exploring a few possible solutions. I'd like to know what plugin or programatic solution would best solve this problem.
Example:
BuildConfig.groovy
plugins{
compile ':cache:1.0.0'
}
MyController.groovy
def getItems(){
def items = MyService.getItems()
[items: items]
}
MyService.groovy
#Cacheable("itemsCache")
class MyService {
def getItems() {
def results
//expensive external web service call
return results
}
}
UPDATE
There were many good options. I decided to go with the plugin approach that Burt suggested. I've included a sample answer with minor changes to above code example to help others out wanting to do something similar. This configuration expires the cache after 24 hours.
BuildConfig.groovy
plugins{
compile ':cache:1.1.7'
compile ':cache-ehcache:1.0.1'
}
Config.groovy
grails.cache.config = {
defaultCache {
maxElementsInMemory 10000
eternal false
timeToIdleSeconds 86400
timeToLiveSeconds 86400
overflowToDisk false
maxElementsOnDisk 0
diskPersistent false
diskExpiryThreadIntervalSeconds 120
memoryStoreEvictionPolicy 'LRU'
}
}
The core plugin doesn't support TTL, but the Ehcache plugin does. See http://grails-plugins.github.com/grails-cache-ehcache/docs/manual/guide/usage.html#dsl
The http://grails.org/plugin/cache-ehcache plugin depends on http://grails.org/plugin/cache but replaces the cache manager with one that uses Ehcache (so you need both installed)
A hack/workaround would be to use a combination of #Cacheable("itemsCache") and #CacheFlush("itemsCache").
Tell the getItems() method to cache the results.
#Cacheable("itemsCache")
def getItems() {
}
and then another service method to flush the cache, which you can call frequently from a Job.
#CacheFlush("itemsCache")
def flushItemsCache() {}
After several hours of fails in battles with SpEL I have won the war in the end!
So as you know Grails cache does not have TTL out of the box. You can stick to ehcache and do some fancy configuration. Or worse add logic flushing it on save/update etc. But my solution is:
#Cacheable(value = 'domainInstance', key="#someId.concat((new java.util.GregorianCalendar().getTimeInMillis()/10000))")
def getSomeStuffOfDb(String someId){
//extract something of db
}
}
and one more thing to point out. You can skip configuration in Config.groovy and it will be created and added automatically itself.
However if your app is under load straight after start it will cause some exceptions.
2017-03-02 14:05:53,159 [http-apr-8080-exec-169] ERROR errors.GrailsExceptionResolver - CacheException occurred when processing request: [GET] /some/get
Failed to get lock for campaignInstance cache creation. Stacktrace follows:
so to avoid that please add config so cache facilities will be ready beforehand.
grails.cache.enabled = true
grails.cache.clearAtStartup = true
grails.cache.config = {
defaults {
maxElementsInMemory 10000
overflowToDisk false
}
cache {
name 'domainInstance'
}
}
GregorianCalendar().getTimeInMillis()/10000 will make TTL ~10sec. /1000 ~1 sec. Pure maths here.
From the grails-cache unit tests(Look for timeToLiveSeconds), I see that you can configure caching at the cache level, not per method call or similar. Using this method, you would configure the settings for grails.cache.config.
You would create a dedicated cache with your time-to-live settings and then reference it in your service.

How to do an upsert / push with mongoid / moped

I'm using Mongoid (v3) to access MongoDB, and want to perform this action:
db.sessionlogs.update(
{sessionid: '12345'}, /* selection criteria */
{'$push':{rows: "new set of data"}}, /* modification */
true /* upsert */
);
This works fine in the mongo shell. It's also exactly what I want since it's a single atomic operation which is important to me as I'm going to be calling it a lot. I don't want to have to do two operations -- a fetch and then an update. I've tried a bunch of things through mongoid, but can't get it to work.
How can I get MongoID out of the way and just send this command to MongoDB? I'm guessing there's some way to do this at the Moped level, but the documentation of that library is basically non-existent.
[Answer found while writing the question...]
criteria = Sessionlogs.collection.find(:sessionid => sessionid)
criteria.upsert("$push" => {"rows" => datarow})
Here is one way to do it:
session_log = SessionLog.new(session_id: '12345')
session_log.upsert
session_log.push(:rows, "new set of data")
Or another:
SessionLog.find_or_create_by(session_id: '12345').
push(:rows, "new set of data")
#push performs an atomic $push on the field. It is explained on the
Atomic Persistence page.
(Note: the examples use UpperCamelCase and snake_case as is Ruby convention.)
Don't go down to moped just yet, you can use find and modify operation to achieve the same thing (with all the default scope and inheritance goodies)
Sample to save an edge in a graph if not existed
edge = {source_id: session[:user_id],dest_id:product._id, name: edge_name}
ProductEdge.where(edge).find_and_modify(ProductEdge.new(edge).as_document,{upsert:true})

Resources