How to pass futures around to different endpoints in dask - dask-distributed

I have a dask cluster (not asynchronous) setup in FastAPI, and I have created two endpoints. One submits the function to the dask cluster and the other gets polled by vuejs every so often and once the status is "finished" it stops polling. However dask has the issue that it forgets about futures if it thinks you do not need them. So I have a dictionary to hold onto them (similar to here. So I used that in my code and in my local container it worked. However deployed in pods on kubernetes I am able to print out the future key and future status to the logs, but the future is not there. The code for this is like as follows:
futures = {}
#router.post('/simulate')
async def simulate(request: Request, background_tasks: BackgroundTasks) -> object:
data = await request.json()
if data is None or not data:
raise HTTPException(status_code=422, detail={
"message": "Json body can't be empty"})
try:
data_is_cached = await get_cache(key=json.dumps(data, cls=CustomJSONEncoder))
if data_is_cached:
return {
"is_cached": True,
"result": data_is_cached
}
else:
# logic to create inputs_dict using data here
future = client.submit(run_simulation, inputs_dict)
futures[future.key] = [future, data]
return {
"is_cached": False,
"key": future.key
}
except Exception as e:
traceback.print_exc()
raise HTTPException(status_code=500, detail={
"message": str(e)})
#router.get('/get_status/{key_id}')
async def check_status(key_id: str, request: Request, background_tasks: BackgroundTasks) -> object:
try:
future = futures[key_id][0]
data = futures[key_id][1]
if 'finished' in future.status:
result = future.result()
background_tasks.add_task(set_cache, key=json.dumps(data, cls=CustomJSONEncoder), data=result)
return {
"statusFinished": True,
"result": result
}
elif "pending" in future.status:
return {
"statusFinished": False,
"result": "pending"
}
else:
return {
"statusFinished": False,
"result": "error"
}
except Exception as e:
traceback.print_exc()
raise HTTPException(status_code=500, detail={
"message": str(e)})
I then looked at dask datasets as a dataset can be shared across dask workers. But this always leave the state in "pending" I have to explicitly call future.result() why defies the purpose of what I am trying to do. This was in my container in localhost.
Here the code for this is:
#router.post('/simulate')
async def simulate(request: Request, background_tasks: BackgroundTasks) -> object:
data = await request.json()
if data is None or not data:
raise HTTPException(status_code=422, detail={
"message": "Json body can't be empty"})
try:
data_is_cached = await get_cache(key=json.dumps(data, cls=CustomJSONEncoder))
if data_is_cached:
return {
"is_cached": True,
"result": data_is_cached
}
else:
# logic to create inputs_dict using data here
future = client.submit(run_simulation, inputs_dict)
client.datasets[future.key] = future
client.datasets[f"{future.key}-data"] = data
return {
"is_cached": False,
"key": future.key
}
except Exception as e:
traceback.print_exc()
raise HTTPException(status_code=500, detail={
"message": str(e)})
#router.get('/get_status/{key_id}')
async def check_status(key_id: str, request: Request, background_tasks: BackgroundTasks) -> object:
try:
future = client.get_dataset(key_id)
data = client.get_dataset(f"{key_id}-data")
if 'finished' in future.status:
result = future.result()
background_tasks.add_task(set_cache, key=json.dumps(data, cls=CustomJSONEncoder), data=result)
return {
"statusFinished": True,
"result": result
}
elif "pending" in future.status:
return {
"statusFinished": False,
"result": "pending"
}
else:
return {
"statusFinished": False,
"result": "error"
}
except Exception as e:
traceback.print_exc()
raise HTTPException(status_code=500, detail={
"message": str(e)})
I have the dask-worker to have 1 worker and 1 thread. Is there not a way to hold on to these futures properly?

Related

How can i fix this error : { "detail": "Authentication credentials were not provided." } on Django RestFramework

I am getting
{"detail": "Authentication credentials were not provided." }
when I run Django Restframework code.
in my settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10,
'NON_FIELD_ERRORS_KEY': 'error',
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
Here is where the culprit lies when i make a request to input values
class CashflowListAPIView(ListCreateAPIView):
serializer_class = CashflowSerializer
queryset = Cashflow.objects.all()
permission_classes = (permissions.IsAuthenticated,)
def perform_create(self,serializer):
return serializer.save(owner=self.request.user)
def get_queryset(self):
return self.queryset.filter(owner = self.request.user)
class CashflowDetailAPIView(RetrieveUpdateDestroyAPIView):
serializer_class = CashflowSerializer
permission_classes = (permissions.IsAuthenticated,IsOwner,)
queryset = Cashflow.objects.all()
lookup_fields = 'id'
def get_queryset(self):
return self.queryset.filter(owner=self.request.user)
mind you, its supposed to work since user has gone through the authentication process VIA swagger API system on localhost:
SWAGGER_SETTINGS = {
'SECURITY_DEFINITIONS': {
'Bearer': {
'type': 'apiKey',
'name': 'Authorization',
'in': 'header'
}
}
}
How can i get my user to successfully input and fetch data without getting the message, { "detail": "Authentication credentials were not provided." }?
Your input is valued and appreciated. Thanks

How to validate an object inside a JSON schema in Karate whether its empty or contains a series of key:value pairs?

I am trying to validate an API response using Karate for either of these two states.
Scenario 1 (when it returns a contractData object that contains a fee key):
{
"customer": {
"financialData": {
"totalAmount": 55736.51,
"CreateDate": "2022-04-01",
"RequestedBy": "user1#test.com"
},
"contractData": {
"Fee": 78.00
}
}
}
Scenario 2 (when it returns an empty contractData object):
{
"customer": {
"financialData": {
"totalAmount": 55736.51,
"CreateDate": "2022-04-01",
"RequestedBy": "user1#test.com"
},
"contractData": {}
}
}
How can I write my schema validation logic to validate both states?
The best thing I could have done is to write it like this:
* def schema = {"customer":{"financialData":{"totalAmount":"#number","CreateDate":"#?isValidDate(_)","RequestedBy":"#string"},"contractData":{"Fee": ##number}}}
* match response == schema
And it seems like it works for both above scenarios, but I am not sure whether this is the best approach or not. Problem with this approach is if I have more than one key:value pair inside "contractData" object and I want to be sure all those keys are present in there when it is not empty, I cannot check it via this approach because for each individual key:value pair, this approach assumes that they could either be present or not and will match the schema even if some of those keys will be present.
Wow, I have to admit I've never come across this case ever, and that's saying something. I finally was able to figure out a possible solution:
* def chunk = { foo: 'bar' }
* def valid = function(x){ return karate.match(x, {}).pass || karate.match(x, chunk).pass }
* def schema = { hey: '#? valid(_)' }
* def response1 = { hey: { foo: 'bar' } }
* def response2 = { hey: { } }
* match response1 == schema
* match response2 == schema

Consumer with message selector not working

I have a simple consumer:
try
{
factory = new NMSConnectionFactory(Settings.Endpoint);
connection = factory.CreateConnection(Settings.UserName, Settings.Password);
connection.ClientId = Settings.Name;
session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
destination = SessionUtil.GetDestination(session, Settings.QueueName, DestinationType.Queue);
consumer = session.CreateConsumer(destination, "portCode = 'GB'", false);
consumer.Listener += new MessageListener(OnMessage);
}
catch
{
throw;
}
I need to apply a selector to get messages when the portCode field is equal to "GB".
This queue receives many messages.
The message is in JSON and a sample of this message is shown below:
{
"message": {
"list": [
{
xxxxxxx
}
]
},
"header": {
"messageCode": "xxxxxx",
"portCode": "GB",
"sourceSystem": "origin",
"messageId": "ca0bf0e0-cefa-4f5a-a80a-b518e7d2f645",
"dateTimeMessage": "2021-04-22T07:12:48.000-0300",
"version": "1.0"
}
}
However, I do not receive messages using the specified "GB" selector.
It seems simple to define selectors, but it is not working for me.
Thanks.
Selectors do not work on the body of the message (i.e. your JSON data). They only work on the headers and properties of the message.

How to set custom error in strong-error-handler when debug mode is false

I'm using Loopback v3.x, and strong-error-handler for handling my project errors. The error response was fine in the development mode but when in production mode, it throws a different error back to the client.
I realised that it was the "debug": false" that makes it throw an { error: { statusCode: 500, message: 'Internal Server Error' } } (based from the Loopback documentation about strong-error-handler)
But I wanted to show my error in the production when I throw new Error('Error Messages') with "debug": false (to keep the sensitive data such as file paths, URLs, and stack traces out from exposure)
Below are my config files:
config.json
{
...
"remoting": {
"rest": {
"normalizeHttpPath": false,
"xml": false,
"handleErrors": false
}
}
}
middleware.development.json
{
"final:after": {
"strong-error-handler": {
"params": {
"debug": true,
"log": true,
"safeFields": [
"code"
]
}
}
}
}
middleware.json
{
"final:after": {
"strong-error-handler": {
"params": {
"debug": false,
"log": true,
"safeFields": [
"code"
]
}
}
}
}
I wanted the response to show the Error that I have thrown, like below:
Instead, now it receives:
I have went to strongloop-error-handler GitHub library but couldn't find any documentation about throwing the original error. Is it possible to do so?
So I went digging around the strong-error-handler library and found out that it is technically possible to do so if we set a statusCode into the error manually, and has to be within 400 - 499.
in buildResponseData() function:
if (data.statusCode >= 400 && data.statusCode <= 499) {
fillBadRequestError(data, err);
} else {
fillInternalError(data, err);
}
https://github.com/strongloop/strong-error-handler/blob/master/lib/data-builder.js#L37
and the fillBadRequestError() will return the original error
function fillBadRequestError(data, err) {
data.name = err.name;
data.message = err.message;
data.code = err.code;
data.details = err.details;
}
https://github.com/strongloop/strong-error-handler/blob/master/lib/data-builder.js#L69
So, before throwing the error, we can set:
const error = new Error();
error.name = 'Custom Error';
error.message = 'Error Message';
error.statusCode = 404;
throw error;
Then it will return the error even with "debug": false mode

Go Unmarshalling Response from API

I have been working with Go and the Bitmex API.
I have the following Bitmex api endpoint:
https://www.bitmex.com/api/v1/leaderboard
This returns an array of JSON objects structured as follows.
[
{
"name": "string",
"isRealName": true,
"profit": 0
}
]
However I get the following incorrect representation of the JSON when I marshal it.
[{0 false } {0 false } ... ]
I know my HTTP request is going through, as when I print the response.Body I get the following
[{"profit":256915996199,"isRealName":true,"name":"angelobtc"} ... ]
Here is the struct I am using to store the marshaled data.
type LeaderboardResponse struct {
profit float64 `json:"profit"`
isRealName bool `json:"isRealName"`
name string `json:"name"`
}
And my main method
func main() {
response, errorResponse := http.Get("https://www.bitmex.com/api/v1/leaderboard")
if response.Status == "200 OK"{
if errorResponse != nil {
fmt.Printf("The HTTP request failed with error %s\n",errorResponse)
} else {
body, errorBody := ioutil.ReadAll(response.Body)
if errorBody != nil {
fmt.Println("There was an error retrieving the body", errorBody)
} else {
leaderboard := []LeaderboardResponse{}
json.Unmarshal([]byte(body),&leaderboard)
if leaderboard != nil {
fmt.Println(leaderboard);
//The result of the statement above and the one below are different
fmt.Println(string(body))
} else {
fmt.Println("leaderboard array is undefined")
}
defer response.Body.Close()
}
}
} else {
fmt.Println("Response received with status ", string(response.Status))
}
}
It appears that the values of struct have not been modifies despite it being assigned the marshaled JSON body
How do I fix this issue?
Furthermore,
How do I add my API credentials to the HTTP request?
How do I access the response header and marshal it?