Hystrix fallback handling 2 dbcall - hystrix

Hystrix fallback issue.
If dbcall1 goes in fallback due to some failure and short-circuit happens, then dbcall2 also goes in fallback evrytime untill the circuit opens.
public class CommandHelloFailure extends HystrixCommand<String> {
private final String name;
public CommandHelloFailure(String name) {
super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
this.name = name;
}`enter code here`
String dbcall1 ()
{
new CommandHelloFailure().execute();
}
String dbcall2()
{
new CommandHelloFailure().execute();
}
#Override
protected String run() {
throw new RuntimeException("this command always fails");
}
#Override
protected String getFallback() {
return "Hello Failure " + name + "!";
}
}
However i want independent fallback for both the method(DB call).

That's because you didn't specify HystrixCommandKey. If you doesn't specify HystrixCommandKey, HystrixCommandKey is derived from the class name. Namely CommandHelloFailure will be used as HystrixCommandKey.
It means that dbcall1 and dbcall2 will share the same circuit breaker.
Because Circuit Break is created for each HystrixCommandKey, not HystrixCommandGroupKey.

Related

BroadcastProcessFunction Processing Delay

I'm fairly new to Flink and would be grateful for any advice with this issue.
I wrote a job that receives some input events and compares them with some rules before forwarding them on to kafka topics based on whatever rules match. I implemented this using a flatMap and found it worked well, with one downside: I was loading the rules just once, during application startup, by calling an API from my main() method, and passing the result of this API call into the flatMap function. This worked, but it means that if there are any changes to the rules I have to restart the application, so I wanted to improve it.
I found this page in the documentation which seems to be an appropriate solution to the problem. I wrote a custom source to poll my Rules API every few minutes, and then used a BroadcastProcessFunction, with the Rules added to to the broadcast state using processBroadcastElement and the events processed by processElement.
The solution is working, but with one problem. My first approach using a FlatMap would process the events almost instantly. Now that I changed to a BroadcastProcessFunction each event takes 60 seconds to process, and it seems to be more or less exactly 60 seconds every time with almost no variation. I made no changes to the rule matching logic itself.
I've had a look through the documentation and I can't seem to find a reason for this, so I'd appreciate if anyone more experienced in flink could offer a suggestion as to what might cause this delay.
The job:
public static void main(String[] args) throws Exception {
// set up the streaming execution environment
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStreamTimeCharacteristic(TimeCharacteristic.IngestionTime);
// read the input from Kafka
DataStream<KafkaEvent> documentStream = env.addSource(
createKafkaSource(getSourceTopic(), getSourceProperties())).name("Kafka[" + getSourceTopic() + "]");
// Configure the Rules data stream
DataStream<RulesEvent> ruleStream = env.addSource(
new RulesApiHttpSource(
getApiRulesSubdomain(),
getApiBearerToken(),
DataType.DataTypeName.LOGS,
getRulesApiCacheDuration()) // Currently set to 120000
);
MapStateDescriptor<String, RulesEvent> ruleStateDescriptor = new MapStateDescriptor<>(
"RulesBroadcastState",
BasicTypeInfo.STRING_TYPE_INFO,
TypeInformation.of(new TypeHint<RulesEvent>() {
}));
// broadcast the rules and create the broadcast state
BroadcastStream<RulesEvent> ruleBroadcastStream = ruleStream
.broadcast(ruleStateDescriptor);
// extract the resources and attributes
documentStream
.connect(ruleBroadcastStream)
.process(new FanOutLogsRuleMapper()).name("FanOut Stream")
.addSink(createKafkaSink(getDestinationProperties()))
.name("FanOut Sink");
// run the job
env.execute(FanOutJob.class.getName());
}
The custom HTTP source which gets the rules
public class RulesApiHttpSource extends RichSourceFunction<RulesEvent> {
private static final Logger LOGGER = LoggerFactory.getLogger(RulesApiHttpSource.class);
private final long pollIntervalMillis;
private final String endpoint;
private final String bearerToken;
private final DataType.DataTypeName dataType;
private final RulesApiCaller caller;
private volatile boolean running = true;
public RulesApiHttpSource(String endpoint, String bearerToken, DataType.DataTypeName dataType, long pollIntervalMillis) {
this.pollIntervalMillis = pollIntervalMillis;
this.endpoint = endpoint;
this.bearerToken = bearerToken;
this.dataType = dataType;
this.caller = new RulesApiCaller(this.endpoint, this.bearerToken);
}
#Override
public void open(Configuration configuration) throws Exception {
// do nothing
}
#Override
public void close() throws IOException {
// do nothing
}
#Override
public void run(SourceContext<RulesEvent> ctx) throws IOException {
while (running) {
if (pollIntervalMillis > 0) {
try {
RulesEvent event = new RulesEvent();
event.setRules(getCurrentRulesList());
event.setDataType(this.dataType);
event.setRetrievedAt(Instant.now());
ctx.collect(event);
Thread.sleep(pollIntervalMillis);
} catch (InterruptedException e) {
running = false;
}
} else if (pollIntervalMillis <= 0) {
cancel();
}
}
}
public List<Rule> getCurrentRulesList() throws IOException {
// call API and get rulles
}
#Override
public void cancel() {
running = false;
}
}
The BroadcastProcessFunction
public abstract class FanOutRuleMapper extends BroadcastProcessFunction<KafkaEvent, RulesEvent, KafkaEvent> {
protected final String RULES_EVENT_NAME = "rulesEvent";
protected final MapStateDescriptor<String, RulesEvent> ruleStateDescriptor = new MapStateDescriptor<>(
"RulesBroadcastState",
BasicTypeInfo.STRING_TYPE_INFO,
TypeInformation.of(new TypeHint<RulesEvent>() {
}));
#Override
public void processBroadcastElement(RulesEvent rulesEvent, BroadcastProcessFunction<KafkaEvent, RulesEvent, KafkaEvent>.Context ctx, Collector<KafkaEvent> out) throws Exception {
ctx.getBroadcastState(ruleStateDescriptor).put(RULES_EVENT_NAME, rulesEvent);
LOGGER.debug("Added to broadcast state {}", rulesEvent.toString());
}
// omitted rules matching logic
}
public class FanOutLogsRuleMapper extends FanOutRuleMapper {
public FanOutLogsJobRuleMapper() {
super();
}
#Override
public void processElement(KafkaEvent in, BroadcastProcessFunction<KafkaEvent, RulesEvent, KafkaEvent>.ReadOnlyContext ctx, Collector<KafkaEvent> out) throws Exception {
RulesEvent rulesEvent = ctx.getBroadcastState(ruleStateDescriptor).get(RULES_EVENT_NAME);
ExportLogsServiceRequest otlpLog = extractOtlpMessageFromJsonPayload(in);
for (Rule rule : rulesEvent.getRules()) {
boolean match = false;
// omitted rules matching logic
if (match) {
for (RuleDestination ruleDestination : rule.getRulesDestinations()) {
out.collect(fillInTheEvent(in, rule, ruleDestination, otlpLog));
}
}
}
}
}
Maybe you can give the complete code of the FanOutLogsRuleMapper class, currently the match variable is always false

Overriding Hystrix command properties specified in .properties file

I need to override command timeout property specified in my application.properties file. Here is what I tried
#Test
public void testTokenQueryTimeout() throws Exception
{
String propertyToSet ="hystrix.command.quickbaseTokenQueryCommand.execution.isolation.thread.timeoutInMilliseconds";
String prop="";
try {
prop = ConfigurationManager.getConfigInstance().getProperty(
propertyToSet).toString();
logger.info("\n\n\noriginal quickbaseTokenQueryCommand timeout ="+prop);
System.setProperty(
propertyToSet,"10");
prop = ConfigurationManager.getConfigInstance().getProperty(
propertyToSet).toString();
logger.info("\n\n\nupdated quickbaseTokenQueryCommand timeout ="+prop);
String response = accountValidation.isValidToken(token);
logger.info(response);
Assert.assertFalse(true);
}
catch (AccountValidationServiceException e)
{
Assert.assertTrue(Constants.ERRCODE_TOKEN_QUERY_TIMED_OUT.equals(e.getErrorCode()));
}
finally {
ConfigurationManager.getConfigInstance().clearProperty(propertyToSet);
System.clearProperty(propertyToSet);
if(!GeneralUtil.isObjectEmpty(System.getProperty(
propertyToSet)))prop = System.getProperty(
propertyToSet);
logger.info("Updated testTokenQueryTimeout timeout ="+prop);
}
}
Notice, System.setProperty(propertyToSet,"10"). With this approach this test case passes i.e. the property gets changed and command times out but another test case fails due to this command timeout though I am clearing the property from System.
I also tried setting the property using ConfigurationManager.getConfigInstance().setProperty(
propertyToSet).toString(),"10"); But in that case, this change of property has no effect and command does not timeout.
Is there something I am missing here.
Please help.
Try using the ConcurrentCompositeConfiguration class
application.properties
hystrix.command.HelloWorldCommand.execution.isolation.thread.timeoutInMilliseconds=200
Command
public class HelloWorldCommand extends HystrixCommand<String> {
public HelloWorldCommand() {
super(HystrixCommandGroupKey.Factory.asKey("HelloWorldGroup"));
}
#Override
protected String run() throws Exception {
TimeUnit.MILLISECONDS.sleep(1100);
return "Hello";
}
}
Test
public class HelloWorldCommandTest {
#Test
public void commandConfigTest() {
String propertyKey = "hystrix.command.HelloWorldCommand.execution.isolation.thread.timeoutInMilliseconds";
ConcurrentCompositeConfiguration config = (ConcurrentCompositeConfiguration) ConfigurationManager.getConfigInstance();
Integer originalTimeout = (Integer) config.getProperty(propertyKey);
config.setOverrideProperty(propertyKey, 1200);
String result = new HelloWorldCommand().execute();
assertThat(result, is("Hello"));
config.setOverrideProperty(propertyKey, originalTimeout);
Integer timeoutValue = (Integer) config.getProperty(propertyKey);
assertThat(timeoutValue, is(originalTimeout));
}
}

how to use selenium with fitnesse

I am creating a small test. In Code behind I have two classes. Pages, LoginPage.
The first part is running. I dont know how to integrate with second part. Currently I am able to open the browser. Also I am trying to use the Page obect model pattern .
Fitnesse code
!|import|
|TestFramework|
!|script|Pages|
|Goto||https://gmail.com|
|LoginPage|CheckRequiredElementsPresent|Pass|
Fixtures
public class Pages
{
string url;
private LoginPage loginPage;
public static void Goto(string url)
{
Browser.Goto(url);
}
}
public class LoginPage
{
static string PageTitle;
[FindsBy(How = How.Id, Using = "TextUsername")]
private static IWebElement username;
[FindsBy(How = How.Id, Using = "TextPassword")]
private static IWebElement password;
[FindsBy(How = How.Id, Using = "_ButtonLogin")]
private static IWebElement submit;
public string IsAtLoginPage()
{
return "";
}
public string CheckRequiredElementsPresent()
{
if (username != null && password != null && submit != null)
{
return "Pass";
}
return "Fail";
}
}
}
You need to do something like below:
Fitnesse Code
!|import|
|TestFramework|
!|script|Pages|
|Goto||https://gmail.com|
|check Required Element|Pass|
You need to call your second class from your Pages class, please see the code changes & fitnesse fixture changes that I've made.
Fixtures
public class Pages
{
string url;
private LoginPage loginPage;
public static void Goto(string url)
{
Browser.Goto(url);
}
// This is what you need to do to refer method of second class.
// This method will be called after Goto method in sequence.
public boolean checkRequiredElement(){
return loginPage.CheckRequiredElementsPresent()
}
}

Request Factory GWT editor change isn't persisting related JDO entities

I'm using (and new to) RequestFactory in GWT 2.5, with JDO entities with a one-to-many relationship, on AppEngine datastore. I've just started using the GWT RequestFactoryEditorDriver to display/edit my objects.
The Driver traverses my objects fine, and displays them correctly. However, when I try to edit a value on the "related" objects, the change doesn't get persisted to the datastore.
When I change b.name on my UI and click "save", I notice only A's persist() call is called. B's persist() is never called. How do I make the editorDriver fire on both ARequest as well as BRequest request contexts? (since what I want is for B's InstanceRequest<AProxy,Void> persist() to be called when my edits are to B objects only.)
Also, AFAICT, if I have an editor on BProxy, any object b that is being shown by the editor (and following the Editor Contract) should automatically be "context.edit(b)"ed by the Driver to make it mutable. However, in my case "context" is an ARequest, not a BRequest.
Do I have to make a ValueAwareEditor like mentioned here: GWT Editor framework
and create a fresh BRequest inside the flush() call and fire it, so that changes to B separately persist in a BRequest before the ARequest is fired?
editorDriver.getPaths() gives me:
"bs"
Also, the driver definitely sees the change to B's property, as editorDriver.isChanged() returns true before I fire() the context.
There are no errors on my client-side or server-side logs, and the Annotation Processor runs with no warnings.
Here's how I setup my driver:
editorDriver = GWT.create(Driver.class);
editorDriver.initialize(rf, view.getAEditor());
final ARequest aRequest = rf.ARequest();
final Request<List<AProxy>> aRequest = aRequest.findAByUser(loginInfo.getUserId());
String[] paths = editorDriver.getPaths();
aRequest.with(paths).fire(new Receiver<List<AProxy>>() {
#Override
public void onSuccess(List<AProxy> response) {
AProxy a = response.get(0);
ARequest aRequest2 = rf.aRequest();
editorDriver.edit(a, aRequest2);
aRequest2.persist().using(a);
}
});
This is how my entities look:
public abstract class PersistentEntity {
public Void persist() {
PersistenceManager pm = getPersistenceManager();
try {
pm.makePersistent(this);
} finally {
pm.close();
}
return null;
}
public Void remove() {
PersistenceManager pm = getPersistenceManager();
try {
pm.deletePersistent(this);
} finally {
pm.close();
}
return null;
}
}
#PersistenceCapable(identityType = IdentityType.APPLICATION)
#Version(strategy=VersionStrategy.VERSION_NUMBER, column="VERSION",
extensions={#Extension(vendorName="datanucleus", key="field-name", value="version")})
public class A extends PersistentEntity {
... (Id, version omitted for brevity)
#Persistent
private String name;
#Persistent
private List<B> bs;
public String getName() {
return name;
}
...
public void setName(String name) {
this.name = name;
}
public List<B> getBs() {
return bs;
}
public void setBs(List<B> bs) {
this.bs = bs;
}
}
... (same annotations as above omitted for brevity)
public class B extends PersistentEntity {
... (Id, version omitted for brevity)
#Persistent
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Here are the proxies:
#ProxyFor(A.class)
public interface AProxy extends EntityProxy {
String getName();
List<BProxy> getBs();
void setName(String name);
void setBs(List<BProxy> bs);
}
#ProxyFor(B.class)
public interface BProxy extends EntityProxy {
String getName();
void setName(String name);
}
Here are my service stubs:
#Service(A.class)
public interface ARequest extends RequestContext {
Request<List<A>> findAByUser(String userId);
InstanceRequest<AProxy, Void> persist();
InstanceRequest<AProxy, Void> remove();
}
#Service(B.class)
public interface BRequest extends RequestContext {
Request<List<A>> findB(String key);
InstanceRequest<BProxy, Void> persist();
InstanceRequest<BProxy, Void> remove();
}
Edit:
I've now changed my ARequest interface and service implementation to support a "saveAndReturn" method, so that I can recursively "persist" "a" on the server side:
Request<UserSandboxProxy> saveAndReturn(AProxy aProxy);
I find now that when I "flush" my RequestFactoryEditorDriver, the client-side context object has my new "b.name" value. However, if I call "context.fire()" and inspect my "saveAndReturn" method on the server side, the resulting server-side object "a", just before I "persist" it, doesn't contain the change to "b.name" on any item of the List.
Why could this be happening? How do I debug why this client-information doesn't go across the wire, to the server?
Options I've considered, tried and ruled out:
1) Ensuring the APT has been run, and there are no warnings/errors on Proxy or Service interfaces
2) Ensuring that my proxies does have a valid setter in AProxy for the List
You have to use a session-per-request pattern for RequestFactory to work properly. More details here: https://code.google.com/p/google-web-toolkit/issues/detail?id=7827

Suggest Addresses in a SuggestBox in GWT/Java

I want to define a SuggestBox, which behaves like the search bar in Google Maps: When you begin to type, real addresses, starting with the typed letters, appear.
I think, that I need to use the Geocoder.getLocations(String address, LocationCallback callback) method, but I have no idea how to connect this with the oracle, which is needed by the suggest box to produce its suggestions.
Can you please give me ideas how do I connect the getLocations Method with the SuggestOracle?
I solved this by implementing a subclass of SuggestBox, which has it's own SuggestOracle. The AddressOracle deals as a Wrapper for the Google Maps Service, for which the class Geocoderin the Google Maps API for GWT offers abstractions.
So here is my solution:
First we implement the Widget for a SuggestBox with Google Maps suggestions
public class GoogleMapsSuggestBox extends SuggestBox {
public GoogleMapsSuggestBox() {
super(new AddressOracle());
}
}
Then we implement the SuggestOracle, which wraps the Geocoder async method abstractions:
class AddressOracle extends SuggestOracle {
// this instance is needed, to call the getLocations-Service
private final Geocoder geocoder;
public AddressOracle() {
geocoder = new Geocoder();
}
#Override
public void requestSuggestions(final Request request,
final Callback callback) {
// this is the string, the user has typed so far
String addressQuery = request.getQuery();
// look up for suggestions, only if at least 2 letters have been typed
if (addressQuery.length() > 2) {
geocoder.getLocations(addressQuery, new LocationCallback() {
#Override
public void onFailure(int statusCode) {
// do nothing
}
#Override
public void onSuccess(JsArray<Placemark> places) {
// create an oracle response from the places, found by the
// getLocations-Service
Collection<Suggestion> result = new LinkedList<Suggestion>();
for (int i = 0; i < places.length(); i++) {
String address = places.get(i).getAddress();
AddressSuggestion newSuggestion = new AddressSuggestion(
address);
result.add(newSuggestion);
}
Response response = new Response(result);
callback.onSuggestionsReady(request, response);
}
});
} else {
Response response = new Response(
Collections.<Suggestion> emptyList());
callback.onSuggestionsReady(request, response);
}
}
}
And this is a special class for the oracle suggestions, which just represent a String with the delivered address.
class AddressSuggestion implements SuggestOracle.Suggestion, Serializable {
private static final long serialVersionUID = 1L;
String address;
public AddressSuggestion(String address) {
this.address = address;
}
#Override
public String getDisplayString() {
return this.address;
}
#Override
public String getReplacementString() {
return this.address;
}
}
Now you can bind the new widget into your web page by writing the following line in the onModuleLoad()-method of your EntryPoint-class:
RootPanel.get("hm-map").add(new GoogleMapsSuggestBox());

Resources