Is there a way to programmatically invoke a WebJob function from another function within the WebJob and still have the output binding work? - azure-webjobs

Here's the code:
[return: Table("AnalysisDataTable", Connection = "TableStorageConnection")]
public static async Task<OrchestrationManagerAnalysisData> InputQueueTriggerHandler(
[QueueTrigger("DtOrchestrnRequestQueueName",
Connection = "StorageQueueConnection")] string queueMsg,
[OrchestrationClient] DurableOrchestrationClient client, ILogger logger)
{
logger.LogInformation($"***DtOrchestrationRequestQueueTriggerHandler(): queueMsg = {queueMsg}");
await ProcessInputMessage(queueMsg, client, logger);
// Below is where the code goes to format the TableStorage Entity called analysisData.
// This return causes the above output binding to be executed, saving analysis data to
// Table Storage.
return analysisData;
}
The above code works fine and saves analysisData to TableStorage.
However when I put the output binding attribute on ProcessInputMessage() which is programatically invoked
rather that invoked as a result of a trigger everything works OK except there is no data output
to Table Storage.
[return: Table("AnalysisDataTable", Connection = "TableStorageConnectionName")]
public static async Task<OrchestrationManagerAnalysisData>
ProcessInputMessage(string queueMsg, DurableOrchestrationClient client, ILogger logger)
{
// Do the processing of the input message.
// Below is where the code goes to format the TableStorage Entity called analysisData.
// This return causes the above output binding to be executed, saving analysis data to
// Table Storage.
return analysisData;
}
QUESTION is there a way to cause an output binding to "trigger" when invoked programatically from another function within the WebJob?
I like the labor saving characteristics of output bindings and want to leverage them as much as possible, while also having well factored code, i.e. tight cohesion in each method.
Thanks,
George

is there a way to cause an output binding to "trigger" when invoked programatically from another function within the WebJob?
In short, No.
You send data by using the return value of the function which apply the output binding attribute in function. So, if you want to invoke another function and write data into Table Storage.
If you want to achieve the idea you want, you need to overwrite the return method. However, it is a package integration method, so I suggest that you could use the TableOperation object that inserts the customer entity to the Table Storage.
TableOperation insertOperation = TableOperation.Insert(customer1);
// Execute the insert operation.
table.Execute(insertOperation);
For more details, you could refer to this article.

Related

Akka get response as ComletedStage from actor

I am referring to api
Patters.ask(actor, msg, duration);
here is sample
class MyActor extends AbstractBehavior{
interface Command{}
interface SomeMessage implements Command{ INSTANCE}
public Reveive<Comamnd> receive(){
return newReceiveBuilder().onMessage(SomeMessage.class, this::someMessage).build();
}
private Behavior<Command> someMessage(SomeMessage ref){
System.out.println("Dru lalal");
}
}
ActorRef<MyActor.Command> myActor = ...;
Future<Object> future = Patterns.ask(myActor, SomeMessage.INSTANCE, Duration.ofMillis(10000));
What is gone be object ?
Obviously this won't compile. Some part of picture is missing, but javadoc doesn't state what.
Call "Patterns.ask" suppose to return future with object, those value is provided by actor as business logic. But there is not business logic in actor. I assume there is suppose to be some kind of convention or mapping for method that returns value with what "Patters.ask" triggers.
Same is true about back logic. I will not able to define receiver since it expect to return Receiver not SomeObject and thus, api want't let me bind result to some message. Only thing I can do is manually pass ComputableFuture
ComputableFuture<MyOBject> future = new ComputableFuture<>();
myActor.tell(new Message(future));
private Behavior<Command> someMessage(Message message){
var result = compute();
message.future.comlete(result);
}
And here we go, I have manually manage everything, also issues with passing non serializable message, lifecycle of objects and so on.
Wrong objects is used. Instead of "AskPattern.ask" for new java typed dsl, I used classic "Patterns.ask".
Most of times new api objects has same object name but located in different package. I used to check only package name becouse while playing with in IDE they always next to each other since name is the same. I got used to ignore the classic "com.akka" objects while playing with api.
And here I got into trap, object name is different and not placed in IDE next to "classic" package object.

Why is it not possible to access objects that seem to be in scope when pausing execution?

I'm learning Dart and Flutter, and I'm finding it a mostly pleasureable experience. I'm making an app that I want to communicate with Amazon AWS resources. However, I'm stuck with an issue that I haven't been able to resolve for a while now.
I'm making a function for getting keys and tokens necessary for making authenticated requests to the API at AWS. I'm using a library function from AWS Amplify to get an AuthSession object. If I set a breakpoint to just after the AuthSession object has been retrieved, it seems as if this object contains some object called AuthSession.credentials. This in turn contains awsAccessKey, awsSecretKey and sessionToken, which are the tokens and keys that I need. I can access them in the debug console when execution is paused.
Future<AWSCredentials> getAWSCredentials() async {
final AuthSession authSession = await Amplify.Auth.fetchAuthSession(
options: CognitoSessionOptions(getAWSCredentials: true));
final a = 1; // I set a breakpoint on this line
//final AWSCredentials awsCredentials = authSession.credentials;
//return awsCredentials;
}
VS Code screenshot of objects in scope at breakpoint
However, if I try to make the function return this AuthSession (by uncommenting the last two lines of the above function), or one of the tokens directly, it doesn't compile anymore and I get the error message
The getter 'credentials' isn't defined for the type 'AuthSession'.
Try importing the library that defines 'credentials', correcting the name to the name of an existing getter, or defining a getter or field named 'credentials'. dart(undefined_getter)
I tried to dig into the code defining the class AuthSession, and it doesn't seem to contain any reference to the credentials object. However, it's obviously there at runtime. Why can't I access it?
The class AuthSession does not contain any member called credentials, so when casting the result of fetchAuthSession() to an AuthSession, it is not possible to access that member. However, the subclass CognitoAuthSession does contain the credentials member, so casting the result to that type allows access to authSession.credentials.
So the call to fetchAuthSession() should be
final CognitoAuthSession authSession = await Amplify.Auth.fetchAuthSession(
options: CognitoSessionOptions(getAWSCredentials: true));

How to return Transaction id, time stamp on execution of invoke function in chaincode?

I need guidance in returning transaction id, time stamp on the client interface after each invoke function call.
I have found that stub.GetTxID() is used to for getting transaction id, but peer.response only take one argument, so i am not able to return the TxID on the client interface.
You can create a response object to capture relevant information, marshal it into json and return it back, something like this:
type ChaincodeResponse struct {
txID string
time *timestamp.Timestamp
}
and then
// rest of the invoke code skipped, here is
// the relevant part:
resp, err := json.Marshal(ChaincodeResponse{
txID: stub.GetTxID(),
time: stub.GetTxTimestamp(),
})
// return json representation of relevant information
// in response
return shim.Success(resp)
I'm working on something at the moment that requires all of our transactions to be timestamped. I tried some things based on your code above but I think the api has moved on considerably since 2017.
Currently, I'm adding a created: stub.GetTxTimestamp() field to all of the things we're putting on the ledger and then reading them later in any queries. Though I'm wondering if the timestamps are already generated and stored, therefore making this unnecessary - do you know if a timestamp is still automatically stored on each item put on the ledger?

SFDC Apex Code: Access class level static variable from "Future" method

I need to do a callout to webservice from my ApexController class. To do this, I have an asycn method with attribute #future (callout=true). The webservice call needs to refeence an object that gets populated in save call from VF page.
Since, static (future) calls does not all objects to be passed in as method argument, I was planning to add the data in a static Map and access that in my static method to do a webservice call out. However, the static Map object is getting re-initalized and is null in the static method.
I will really appreciate if anyone can give me some pointeres on how to address this issue.
Thanks!
Here is the code snipped:
private static Map<String, WidgetModels.LeadInformation> leadsMap;
....
......
public PageReference save() {
if(leadsMap == null){
leadsMap = new Map<String, WidgetModels.LeadInformation>();
}
leadsMap.put(guid,widgetLead);
}
//make async call to Widegt Webservice
saveWidgetCallInformation(guid)
//async call to widge webserivce
#future (callout=true)
public static void saveWidgetCallInformation(String guid) {
WidgetModels.LeadInformation cachedLeadInfo =
(WidgetModels.LeadInformation)leadsMap.get(guid);
.....
//call websevice
}
#future is totally separate execution context. It won't have access to any history of how it was called (meaning all static variables are reset, you start with fresh governor limits etc. Like a new action initiated by the user).
The only thing it will "know" is the method parameters that were passed to it. And you can't pass whole objects, you need to pass primitives (Integer, String, DateTime etc) or collections of primitives (List, Set, Map).
If you can access all the info you need from the database - just pass a List<Id> for example and query it.
If you can't - you can cheat by serializing your objects and passing them as List<String>. Check the documentation around JSON class or these 2 handy posts:
https://developer.salesforce.com/blogs/developer-relations/2013/06/passing-objects-to-future-annotated-methods.html
https://gist.github.com/kevinohara80/1790817
Side note - can you rethink your flow? If the starting point is Visualforce you can skip the #future step. Do the callout first and then the DML (if needed). That way the usual "you have uncommitted work pending" error won't be triggered. This thing is there not only to annoy developers ;) It's there to make you rethink your design. You're asking the application to have open transaction & lock on the table(s) for up to 2 minutes. And you're giving yourself extra work - will you rollback your changes correctly when the insert went OK but callout failed?
By reversing the order of operations (callout first, then the DML) you're making it simpler - there was no save attempt to DB so there's nothing to roll back if the save fails.

actionscript web services event fires off to late

I have a web service which is working find with the data proxy.
In this web service I have some functions I like to call and assign the results to a variable.
I found some example on this and below is what I have come up with.
Now all works but my event is being fired to late in the process. What I mean is once I call the getAdData() function and then call the webservice function getBleedAt() I need my event to fire off. what happening is the event is being fire at the end of the hold routine so I get my data to late.
I try using the dispatchEvent but can't get that to work. the web service function is returning a XML structure
public function getAdddata(adnum:String){
var WS:WebService = new WebService();
WS.getBleedAt.addEventListener("result", GetInfo);
WS.getBleedAt.resultFormat = 'e4x';
WS.loadWSDL(URL);
WS.getBleedAt(adnum);
}
private function GetInfo(evt:ResultEvent):void {
var myObj:Object = evt.result as Object;
trace(myObj.BleedAt.toString());
}
The call to the web service returns asynchronously so your result handler (the GetInfo method) is the earliest point at which the result data is available to you. Therefore, any code which needs to access the result data needs to be triggered from the GetInfo method.