I was trying to retrieve cached data (redis) from redis using node js which was set using a .Net core 3.1 application
The code snippet which I was used to set cache is as below
nuget package : Microsoft.Extensions.Caching.StackExchangeRedis v 5.0.0 (Eventhough this is deprecated this is the version which is compatible with .Net core 3.1)
public async Task SetCache(dynamic data, string cacheKey)
{
try
{
if (_redisConfig.EnableCache == true)
{
string cachedDataString = JsonSerializer.Serialize(data);
var dataToCache = Encoding.UTF8.GetBytes(cachedDataString);
// Add the data into the cache
cacheKey = _redisConfig.Env + "_" + cacheKey;
await _cache.SetAsync(cacheKey, dataToCache, _options);
}
}
catch (Exception)
{
return;
}
}
Below is the code I used to retrieve cache using node js
npm package: redis: "^4.5.1",
exports.getRedisData = async (key) => {
try {
return await redisClient.get(key);
} catch (error) {
console.log(error);
return null
}
}
after executing the above solution the result I got is,
message:
'WRONGTYPE Operation against a key holding the wrong kind of value'
Snap shot of the above error
Can anyone give me a clue to fix this ?
With the help of #JsonPan's answer, I was able to retrieve the data from Redis with a very simple change in my code. Here I have added my solution for anyone who may get the same issue as me.
By using hGet instead of get I was able to retrieve the Hashed data. (hGet is used to get Hashed data while get is used to retrieve string data)
exports.getRedisData = async (key) => {
try {
return await redisClient.hGet(key,"data");
} catch (error) {
console.log(error);
return null
}
}
Related
Apologies for asking this question - I know there are tons of information about async functions out there but I seem to have tried everything and cannot find a solution..
First of all let me outline the architecture of my program. There are two scripts: a main server script (node.js, express), which processes GET requests and provider script, which deals with the blockchain in the background to return some values. The server script is responsible for invoking a method that returns a value from the provider. The provider does all the work.
The snippet of the provider script:
getInfo(index, account, key) {
//Waiting on an asynchronous method, which does some work in the blockchain in the background; everything functions as it should be
try {
await this.getBlockchain
(
index
, account
, key
).then(result => {
// Here instead I invoke a SYNCHRONOUS method, which simply formats the response in a correct way
const reply = this.sendReply(result)
console.log(reply) //Logs the correct reply in the format in which the server is expecting it
return reply;
});
}
catch (error) {
return { error: 003, result: false };
}
}
The snippet of the server script:
server.get("/getAccount", async (req, res) => {
let index = req.query.index;
let account = req.query.account;
let key = req.query.key;
// Here I also check for the validity of the query values, irrelevant to this issue
// The provider class is imported as provider, hence, the provider.method (this has been tested many times before)
try {
await provider.getInfo(index, account, key).then(reply => {
const { error: infoError, result: infoValue } = reply
if (infoError == false) {
res.send(`${infoValue}`);
} else {
res.send(`${infoError}`);
};
});
}
catch (error) {
res.send("008");
}
}
);
I honestly have no idea how to approach this; I tried self-contained async function on the server side as well as different syntax but the reply is always undefined even though the reply from a synchronous call in the provider is correct.
Could someone help me to understand what I'm doing wrong? This is my first time working with async with numerous scripts and functions and I'm finding it very confusing.
Thank you so much!
With your current structure, you need to return the result of the await so that the top level of your function is returning something from the async function.
async getInfo(index, account, key) {
try {
let retVal = await this.getBlockchain(index, account, key).then(result => {
return this.sendReply(result);
});
return retVal;
} catch (error) {
return { error: 003, result: false };
}
}
But, really, it's a better coding style to not mix await and .then() and to just go with one style like this:
async getInfo(index, account, key) {
try {
let result = await this.getBlockchain(index, account, key);
return this.sendReply(result);
} catch (error) {
return { error: 003, result: false };
}
}
Note, this function never rejects because it's catching its own rejections and turning it into a resolved value. So, the caller cannot use .catch() to see errors. The caller must always check for the error property in the resolved object. This is not usually how you program with promises. It can be made to work, but often does not meet the expectations of the caller (as errors are usually communicated back via rejected promises).
This has to be a dup. but... Don't mix await and .then.
You simply try/catch around await.
try {
const reply = await provider.getInfo(index, account, key);
const { error: infoError, result: infoValue } = reply
if (infoError == false) {
res.send(`${infoValue}`);
} else {
res.send(`${infoError}`);
};
} catch (error) {
res.send(500);
}
I try to execute this code and receive current blockchain block number
nodeInteraction.currentHeight('https://nodes.wavesplatform.com/').then((res) => {
console.log(res);
});
I did not forget to import the library
import { invokeScript, broadcast, nodeInteraction, waitForTx } from '#waves/waves-transactions';
This code is executed correctly.
nodeInteraction.accountData(dappaddress, baseUri).then((v) => {
window.dAppData = v;
if (v) {
window.dAppDataKeys = Object.keys(v);
console.log("dApp Account data:");
console.log(v);
console.log(JSON.stringify(v));
}
});
I'm using below library
https://wavesplatform.github.io/waves-transactions/globals.html#currentheight
I find an answer) I forgot to re-build my React app. Sorry.
I have a class with a few functions that I need to be async, but adding async in front of the function name gives me an error when compiling. (Testing with just one function atm)
class cataAPIService {
async getRouteDetails(route) {
var busID;
for(var i = 0; i < catabusRoutes.BUS_ROUTE_ID.buses.length; i++) {
if(catabusRoutes.BUS_ROUTE_ID.buses[i].name === route) {
busID = catabusRoutes.BUS_ROUTE_ID.buses[i].id;
console.log("Got bus id: " + busID);
}
}
var deferred = Promise.defer();
try {
const data = await axios.get("https://realtime.catabus.com/InfoPoint/rest/RouteDetails/Get/" + route);
console.log(data)
deferred.resolve(data)
} catch (error) {
console.log("Error in API call")
deferred.reject(error)
}
return deferred.promise
}
Removing async it complies fine but I lose the functionality that I need. Am I making a silly mistake and missing it? Thanks
Picture of console error:
Functions deploy to node 6 by default (you can see that in your console output). node 6 doesn't support async/await syntax. If you want to use async/await, you have to either deploy to node 8 (in beta), or use some sort of transpiled language like TypeScript.
This is correct syntax. Async functions are fully supported since Node 8. Syntax error will only occur if older Node version is used. Node should be updated to newer version if possible.
The code uses deferred antipattern and doesn't require async function. It could be:
async getRouteDetails(route) {
var busID;
for(var i = 0; i < catabusRoutes.BUS_ROUTE_ID.buses.length; i++) {
if(catabusRoutes.BUS_ROUTE_ID.buses[i].name === route) {
busID = catabusRoutes.BUS_ROUTE_ID.buses[i].id;
console.log("Got bus id: " + busID);
}
}
return axios.get("https://realtime.catabus.com/InfoPoint/rest/RouteDetails/Get/" + route)
.then(data => {
console.log(data);
return data;
})
.catch(error => {
console.log("Error in API call");
throw error;
});
}
Check your Node.js version.
Async functions are not supported by Node versions older than version 7.6.
You'll need to transpile your code (e.g. using Babel) to a version of JS that Node understands if you are using an older version.
So my app updates the information inside locally when i call UpdateSync on the table but it doesn't update the online database? Am I doing something wrong?
IMobileServiceSyncTable<Models.About_user> about_user_table;
Update_my_table(Object Item)
{
Models.About_user About_user = (Models.About_user)Item;
await about_user_table.UpdateAsync(About_user);
IMobileServiceSyncTable<Models.About_user> about_user_table;
}
So All I had to is put that on the bottom of my updatesync. Note: this didnt work unless I explicitly had a variable in my about_user model called version like [JsonProperty(PropertyName = "Version")]
public string Version { get; set; }
await about_user_table.UpdateAsync(About_user);
try
{
await Client.SyncContext.PushAsync();
/// await about_user_table.PullAsync("all About_user", about_user_table.CreateQuery());
}
catch (MobileServicePushFailedException ex)
{
if (ex.PushResult != null)
{
foreach (var error in ex.PushResult.Errors)
{
await ResolveConflictAsync(error,"about_user_table");
}
}
}
async Task ResolveConflictAsync(MobileServiceTableOperationError error, string table_name)
{
var serverItem = error.Result.ToObject<About_user>();
var localItem = error.Item.ToObject<About_user>();
// Note that you need to implement the public override Equals(TodoItem item)
// method in the Model for this to work
if (serverItem.Equals(localItem))
{
// Items are the same, so ignore the conflict
await error.CancelAndDiscardItemAsync();
return;
}
// Client Always Wins
localItem.Version = serverItem.Version;
await error.UpdateOperationAsync(JObject.FromObject(localItem));
}
According to your code, you are using the sync table (IMobileServiceSyncTable), for the UpdateAsync operation, it would update your local SQLite database. In order to update your online database, you need to execute the Push operation by using the following code:
await Client.SyncContext.PushAsync();
Note: when executing the push operation, you may need to handle Conflict Resolution. For more details, you could refer to adrian's book about Handling Conflict Resolution and An Offline Client.
Moreover, you could use client.GetTable<Model>() for constructing an online table and do CUD changes against your online table. For more details, you could refer to here. Additionally, you could follow here about offline synchronization.
My removeObjects function has me stummped.The function is suppose to syncronoulsy get a list of objects in an S3 bucket then asyncronously removes the objects. Repeat if the list was truncated, until the there are no more objects to remove. (AWS doesn't provide the total count of objects in the bucket and listObjects pages the results.)
What am I doing wrong / why doesn't my function work? The solution should exploit single thread and async nature of JS. For the bounty I am hoping for an answer specific to the module. The git repo is public if you want to see the entire module.
export function removeObjects(params: IS3NukeRequest): Promise<S3.Types.DeleteObjectsOutput> {
const requests: Array<Promise<S3.Types.DeleteObjectsOutput>> = [];
let isMore;
do {
listObjectsSync(params)
.then((objectList: S3.Types.ListObjectsV2Output) => {
isMore = objectList.ContinuationToken = objectList.IsTruncated ? objectList.NextContinuationToken : null;
requests.push(params.Client.deleteObjects(listObjectsV2Output2deleteObjectsRequest(objectList)).promise());
})
.catch((err: Error) => { Promise.reject(err); });
} while (isMore);
return Promise.all(requests);
}
export async function listObjectsSync(params: IS3NukeRequest): Promise<S3.Types.ListObjectsV2Output> {
try {
return await params.Client.listObjectsV2(s3nukeRequest2listObjectsRequest(params)).promise();
} catch (err) {
return Promise.reject(err);
}
}
Thanks.
The thing is that listObjectsSync function returns a Promise, so you need to treat it as an async function and can't just use a loop with it. What you need to do is to create a chain of promises while your isMore is true, I've done it using a recursive approach (I'm not pro in TS, so please check the code before using it). I also haven't tried the code live, but logically it should work :)
const requests: Array<Promise<S3.Types.DeleteObjectsOutput>> = [];
function recursive(recursiveParams) {
return listObjectsSync(recursiveParams).then((objectList: S3.Types.ListObjectsV2Output) => {
let isMore = objectList.ContinuationToken = objectList.IsTruncated ? objectList.NextContinuationToken : null;
requests.push(params.Client.deleteObjects(listObjectsV2Output2deleteObjectsRequest(objectList)).promise());
if (isMore) {
//do we need to change params here?
return recursive(recursiveParams)
}
//this is not necessary, just to indicate that we get out of the loop
return true;
});
}
return recursive(params).then(() => {
//we will have all requests here
return Promise.all(requests);
});