Updating the Resilience4j CircuitBreaker Properties in Micronaut while the app is running - properties

Resilience4j version: 1.7.1
Java version: 11
Micronaut version: 3.2.7
Can we change the CircuitBreaker Properties of an instance dynamically while the application is running?
The following returns an existing Bean or creates a new one.
/**
* Returns a managed {#link CircuitBreaker} or creates a new one with a custom CircuitBreaker
* configuration.
*
* #param name the name of the CircuitBreaker
* #param config a custom CircuitBreaker configuration
* #return The {#link CircuitBreaker}
*/
CircuitBreaker circuitBreaker(String name, CircuitBreakerConfig config);
At start up of the application, I am doing this to create the CircuitBreakerRegistry and adding an instance myInstanceA to the circuitBreakerRegistry entryMap.
// Create a custom configuration CircuitBreaker
val circuitBreakerConfig: CircuitBreakerConfig = CircuitBreakerConfig.custom()
.slidingWindowSize(10)
.minimumNumberOfCalls(5)
.permittedNumberOfCallsInHalfOpenState(3)
.automaticTransitionFromOpenToHalfOpenEnabled(true)
.waitDurationInOpenState(Duration.ofMillis(5000))
.failureRateThreshold(50F)
.build()
circuitBreakerRegistry = CircuitBreakerRegistry.of(circuitBreakerConfig)
val cb: CircuitBreaker = circuitBreakerRegistry.circuitBreaker("myInstanceA", circuitBreakerConfig)
After start up, at a later time, if I want to change the failureRateThreshold to 70F for the instance myInstanceA, is that an option in Micronaut?

Related

Pass codeception test name to browserstack

I want to pass my test names to browserstack, so that they are logged in the session value (name) within the browserstack interface
In my Acceptance helper I have the following method defined
/**
* HOOK: before test
*
* We use this method to set the test name which will be logged in BrowserStack
* https://www.browserstack.com/automate/capabilities
* #param \Codeception\TestInterface $test
*/
public function _before(\Codeception\TestInterface $test)
{
codecept_debug('_before');
codecept_debug($this->getModule('WebDriver')->_getConfig()['capabilities']);
$config['capabilities'] = $this->getModule('WebDriver')->_getConfig()['capabilities'];
$config['capabilities']['name'] = $test->getName();
$this->getModule('WebDriver')->_setConfig($config);
codecept_debug($this->getModule('WebDriver')->_getConfig()['capabilities']);
}
There are a few issues with my approach
This event seems to fire after the test is logged in browserstack (which is my main issue - I'm looking for the right place to inject this name value)
The tests would sometimes be logged under the wrong names - several tests will use the same name
Which event should I use to achieve my goals?
Looking through codeception and in particular webdriver source code, I saw this:
https://github.com/Codeception/Codeception/blob/2.5/src/Codeception/Module/WebDriver.php#L394
/**
* Change capabilities of WebDriver. Should be executed before starting a new browser session.
* This method expects a function to be passed which returns array or [WebDriver Desired Capabilities](https://github.com/facebook/php-webdriver/blob/community/lib/Remote/DesiredCapabilities.php) object.
* Additional [Chrome options](https://github.com/facebook/php-webdriver/wiki/ChromeOptions) (like adding extensions) can be passed as well.
*
* ```php
* <?php // in helper
* public function _before(TestInterface $test)
* {
* $this->getModule('WebDriver')->_capabilities(function($currentCapabilities) {
* // or new \Facebook\WebDriver\Remote\DesiredCapabilities();
* return \Facebook\WebDriver\Remote\DesiredCapabilities::firefox();
* });
* }
* ```
*
* to make this work load `\Helper\Acceptance` before `WebDriver` in `acceptance.suite.yml`:
*
* ```yaml
* modules:
* enabled:
* - \Helper\Acceptance
* - WebDriver
* ```
*
* For instance, [**BrowserStack** cloud service](https://www.browserstack.com/automate/capabilities) may require a test name to be set in capabilities.
* This is how it can be done via `_capabilities` method from `Helper\Acceptance`:
*
* ```php
* <?php // inside Helper\Acceptance
* public function _before(TestInterface $test)
* {
* $name = $test->getMetadata()->getName();
* $this->getModule('WebDriver')->_capabilities(function($currentCapabilities) use ($name) {
* $currentCapabilities['name'] = $name;
* return $currentCapabilities;
* });
* }
* ```
* In this case, please ensure that `\Helper\Acceptance` is loaded before WebDriver so new capabilities could be applied.
This seems to produce the same bugs as my original question in that,
Some tests don't have their names set
Some tests have the name of the previous test set
EDIT:
The reason the above was happening, was because in my environment file/definition of the device there was a declaration of
modules:
enabled:
- WebDriver
Removing the enabled and webdriver definition allows the fall back on the acceptance.suite.yml which then works correctly as intended

Custom CXF Conduit

I want to custom a CXF Conduit in my application, but i don't know how to implement it and add it in client code.
I want to implement it as custom destination that i have done as follows:
Step1: i create a MyDestinationFactory class
class MyDestinationFactory extends AbstractTransportFactory implements DestinationFactory {
....
}
Step 2: i add this Destination in the server code:
JaxWsServerFactoryBean serverFactory;
MyDestinationFactory destFac = new MyDestinationFactory();
serverFactory.setDestinationFactory(destFac);
It works with the custom destination.
=> How to customize a CXF Conduit ? I read here http://cxf.apache.org/docs/custom-transport.html but i don't use it.
Bus bus = BusFactory.getThreadDefaultBus();
MyTransportFactory customTransport = new MyTransportFactory();
ConduitInitiatorManager extension = bus.getExtension(ConduitInitiatorManager.class);
extension.registerConduitInitiator(MyTransportFactory.TRANSPORT_ID, customTransport);

Expected ' ' to be an inline constant. Java -> Groovy

I am using a custom annotation in my groovy script:
#Retention(RetentionPolicy.RUNTIME)
public #interface ScriptManifest {
/**
* Sets the scripts publicity mode.
* #return ScriptMode
*/
ScriptMode mode();
/**
* Sets the type of script we are using.
* #return ScriptType
*/
Class<? extends ScriptContext>[] type();
/**
* Sets the name of the script.
* #return name
*/
String script_name();
/**
* Sets the author of the script.
* #return author
*/
String author();
}
Creating the test script, my IntelliJ shows the error " Expected 'ScriptMode.PUBLIC' to be an inline constant" and same for TestContext.class. The script functions and runs fine I just am not sure as to why it is showing this for me as if it is an error.
#ScriptManifest(mode = ScriptMode.PUBLIC, type = TestContext.class, script_name = "Test", author = "Jake")
class Test extends Script {
#Override
void prepare() {
println "no" + getName()
}
}
Fixed the issue doing the following: I was trying to compile it in my Maven project with the javac, I added a new groovy module and compiled it with groovyc and it works fine now.

Symfony3 Profiler Storage

in the Docs
http://symfony.com/doc/master/cookbook/profiler/storage.html
you still can find Information about Profiler Storage.
I just checked the code and could not find any clues how to set a custom storage.
I also find no Documentation stating this except some #legacy notes in the Original Source at 2.8.
Is there a Reason why this was removed?
I was using redis to store this data with a lifetime of eta 1hour.
Now I need to run a manual cleanup to whipe all files in that directory.
If anybody has some clues or hints on helping me with this issue are appreceated ^^
Chris
Thanks to the Tip of Matteo I was able to solve this quite flexible.
The Team of Symfony removed this, because it was hard coded into the Profiler Subsystem.
Instead of fixing this by adding a class parameter I had to solve it. :)
Ok, here is the code, If somebody needs this to.
First of all we need the Original Classes from Symfony 2.7 (at least I reused them as I only need the Redis Option ( I use it, because I can Compress the data using igbinary)
Next you need to implement a Compiler Pass.
namespace AcmeBunlde\DependencyInjection\CompilerPass;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class ProfilerCompilerPass implements CompilerPassInterface
{
/**
* You can modify the container here before it is dumped to PHP code.
*
* #param ContainerBuilder $container
*/
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('profiler');
$definition->addArgument('%acmebundle.profiler.defaultEnabled%');
$definition->addArgument('%acmebundle.profiler.class%');
$definition->addArgument('%acmebundle.profiler.dsn%');
$definition->addArgument('%acmebundle.profiler.username%');
$definition->addArgument('%acmebundle.profiler.password%');
$definition->addArgument('%acmebundle.profiler.ttl%');
$definition->setClass('acmebundle\Profiler\Profiler');
}
}
This needs to be loaded inside the Bundle Loader:
public function build(ContainerBuilder $container)
{
...
$container->addCompilerPass(new ProfilerCompilerPass());
}
After this we need to add the Configuration for the New Profiler Storage in the DependencyInjection Folder.
namespace AcmeBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* This is the class that validates and merges configuration from your app/config files
*
* To learn more see {#link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
* #author Chris
*/
class Configuration implements ConfigurationInterface
/**
* {#inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('library');
$rootNode
->children()
->arrayNode('profiler')
->addDefaultsIfNotSet()
->children()
->booleanNode('defaultStorage')
->defaultTrue()
->end()
->scalarNode('class')
->defaultValue('')
->end()
->scalarNode('dsn')
->defaultValue('')
->end()
->scalarNode('username')
->defaultValue('')
->end()
->scalarNode('password')
->defaultValue('')
->end()
->scalarNode('ttl')
->defaultValue('3600')
->end()
->end()
->end();
return $treeBuilder();
}
}
Now set the Default Values in The Dependency Injection Bundle Loader
<?php
namespace AcmeBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
/**
* This is the class that loads and manages your bundle configuration
*
* To learn more see {#link http://symfony.com/doc/current/cookbook/bundles/extension.html}
* #author Chris
*/
class AcmeExtension extends Extension
{
/**
* {#inheritdoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
...
$container->setParameter('acmebundle.profiler.defaultEnabled',$config['profiler']['defaultStorage']);
$container->setParameter('acmebundle.profiler.class',$config['profiler']['class']);
$container->setParameter('acmebundle.profiler.dsn',$config['profiler']['dsn']);
$container->setParameter('acmebundle.profiler.username',$config['profiler']['username']);
$container->setParameter('acmebundle.profiler.password',$config['profiler']['password']);
$container->setParameter('acmebundle.profiler.ttl',$config['profiler']['ttl']);
...
}
...
}
As Last Step you need to build a basic container for adding the new Profiler Handler.
I have choosen to implement it not to complex:
<?php
namespace AcmeBundle\Profiler;
use Psr\Log\LoggerInterface;
use \Symfony\Component\HttpKernel\Profiler\Profiler as ProfilerSrc;
use Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface;
/**
* Profiler.
*/
class Profiler extends ProfilerSrc
{
public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger, $defaultEnabled=true,$class=null,$dsn=null,$username=null,$password=null,$ttl=3600)
{
if($defaultEnabled!==true)
{
$storage = new $class($dsn,$username,$password,$ttl);
}
parent::__construct($storage , $logger);
}
}
I have also added a Library to define the Constructor of the Storage Interface.
<?php
namespace AcmeBundle\Profiler;
use Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface as ProfilerStorageSource;
interface ProfilerStorageInterface extends ProfilerStorageSource
{
/**
* ProfilerStorageInterface constructor.
*
* #param $dsn
* #param $username
* #param $password
* #param $ttl
*/
public function __construct($dsn,$username,$password,$ttl);
}
All you need to do now is to define some Options in your config_dev.yml file.
acmebundle:
profiler:
defaultEnabled: false
class:CLASSNAME INCLUDING NAMESPACE
dsn: redis://localhost/1
username:
password
ttl: 3600
with defaultEnabled = true you can reenable to Original Handler.
the rest is, I believe self explaining.
username + password is from the original feature set.
(ttl == lifetime)
I hope this helps somebody else as well :)
Is marked as deprecated since 2.8 with the suppression in the 3.0. I can't find any motivation about in the PR. The doc is not yet updated as you mention.
The only suggestion is about a comment in this issue:
If you want to use your own implementation of a profiler storage,
then just override the profile.storage service.
Hope this help

Maven: How to check if an artifact exists?

How do I check from within a Mojo if an artifact already exists in the local repository?
I'm installing large binaries into the local Maven repository and I need to know if they already exist before attempting to download them.
Solved with the help of http://docs.codehaus.org/display/MAVENUSER/Mojo+Developer+Cookbook
/**
* The local maven repository.
*
* #parameter expression="${localRepository}"
* #required
* #readonly
*/
#SuppressWarnings("UWF_UNWRITTEN_FIELD")
private ArtifactRepository localRepository;
/**
* #parameter default-value="${project.remoteArtifactRepositories}"
* #required
* #readonly
*/
private List<?> remoteRepositories;
/**
* Resolves Artifacts in the local repository.
*
* #component
*/
private ArtifactResolver artifactResolver;
/**
* #component
*/
private ArtifactFactory artifactFactory;
[...]
Artifact artifact = artifactFactory.createArtifactWithClassifier(groupId, artifactId, version, packagingType, classifier);
boolean artifactExists;
try
{
// Downloads the remote artifact, if necessary
artifactResolver.resolve(artifact, remoteRepositories, localRepository);
artifactExists = true;
}
catch (ArtifactResolutionException e)
{
throw new MojoExecutionException("", e);
}
catch (ArtifactNotFoundException e)
{
artifactExists = false;
}
if (artifactExists)
System.out.println("Artifact found at: " + artifact.getFile());
If you want to check if a remote artifact exists without downloading it, you can use the Aether library to do the following (based on http://dev.eclipse.org/mhonarc/lists/aether-users/msg00127.html):
MavenDefaultLayout defaultLayout = new MavenDefaultLayout();
RemoteRepository centralRepository = new RemoteRepository.Builder("central", "default", "http://repo1.maven.org/maven2/").build();
URI centralUri = URI.create(centralRepository.getUrl());
URI artifactUri = centralUri.resolve(defaultLayout.getPath(artifact));
HttpURLConnection connection = (HttpURLConnection) artifactUri.toURL().openConnection();
connection.setRequestMethod("HEAD");
connection.connect();
boolean artifactExists = connection.getResponseCode() != 404;
With following dependency: org.eclipse.aether:aether-util:0.9.0.M2 and following imports:
import java.net.HttpURLConnection;
import java.net.URI;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.util.repository.layout.MavenDefaultLayout;
Since the answer which is accepted as correct, is no longer pointing to valid URL-s and because I know a better way, I am posting a new answer.
There's the wagon-maven-plugin, which has an exist goal. The documentation is a bit inaccurate, but you can use that.
Code-wise, you can have a look at the DefaultWagonDownload class' exists method:
/**
*
* #param wagon - a Wagon instance
* #param resource - Remote resource to check
* #throws WagonException
*/
public boolean exists( Wagon wagon, String resource )
throws WagonException
{
return wagon.resourceExists( resource );
}
If you expect your artifacts being present in a remote maven repository, I'd suggest you simply use the copy mojo of the maven-dependency-plugin.
It will use normal maven resolution mechanism for retrieving artifacts so will not download something that is already in the local repository.
In a plugin, when using maven 2 (not sure about maven3) you can use the mojo executor to call a mojo from within you code easily.