Get Operation by Name in Google Speech to Text, with nodejs - node.js

I'm using Google Speech to Text Node.js client.
When starting long-running speech transcription, I need to split the operation in two steps.
1. Start the transcription, and return the "name".
2. Ask for the status of the operation.
Ie replicating https://cloud.google.com/speech-to-text/docs/async-recognize#speech-async-recognize-gcs-protocol in nodejs.
My problem is to figure out how to create an OperationsClient, and to make the getOperation({name}) to actually return the result of the transcription.
I do run this code inside two firebase cloud functions:
1. The one that starts the trancscription, and then return the "name". This one works really well with the SpeechClient.
2. Another one that should call operationsClient.getOperation aka the same as curl to "https://speech.googleapis.com/v1/operations/"
import gax, {GrpcClient, GrpcClientOptions, lro} from "google-gax";
const gaxOpts = {
clientConfig: {}
}
const gaxGrpc = new GrpcClient(gaxOpts);
...
app.get('/operations/:googleSpeechRef', async (req, res) => {
const googleSpeechRef = req.params.googleSpeechRef;
const operationsClient = lro({
auth: gaxGrpc.auth,
grpc: gaxGrpc.grpc,
}).operationsClient(gaxOpts);
try {
const [responses] = await operationsClient.getOperation({name: googleSpeechRef},{});
if (responses) {
const operation = responses[0]
console.log("getOperation. responses: ", responses)
const initialApiResponse = responses[1]
operation
.on("complete", (longRunningRecognizeResponse /*, longRunningRecognizeMetadata, finalApiResponse*/) => {
// Adding a listener for the "complete" event starts polling for the
// completion of the operation.
const speechRecognitionResults = longRunningRecognizeResponse.results as ISpeechRecognitionResult[]
// resolve(speechRecognitionResults)
console.log("complete: ", speechRecognitionResults)
})
.on("progress", async (longRunningRecognizeMetadata /*, apiResponse*/) => {
// Adding a listener for the "progress" event causes the callback to be
// called on any change in metadata when the operation is polled.
const percent = longRunningRecognizeMetadata.progressPercent
console.log("progress. Percent", longRunningRecognizeMetadata.progressPercent /*, apiResponse*/)
})
.on("error", (error: Error) => {
// Adding a listener for the "error" event handles any errors found during polling.
// reject(error)
console.log("error: ", error)
})
res.contentType("application/json").status(200).send(JSON.stringify(initialApiResponse))
} else {
res.send(404)
}
} catch (error) {
console.error("Failed to fetch operation by googleSpeechRef: ", googleSpeechRef, ". Error: ", error);
res.status(500).send(serializeError(error))
}
}
The error i get is:
{
"code": 13,
"details": "Not enough responses received",
"metadata":{
"internalRepr":{}
},
"note": "Exception occurred in retry method that was not classified as transient",
"name": "Error",
"message": "Not enough responses received",
"stack": "Error: Not enough responses received\n at Http2CallStream.call.on (/srv/node_modules/#grpc/grpc-js/build/src/client.js:102:45)\n at emitOne (events.js:121:20)\n at Http2CallStream.emit (events.js:211:7)\n at Http2CallStream.endCall (/srv/node_modules/#grpc/grpc-js/build/src/call-stream.js:74:18)\n at /srv/node_modules/#grpc/grpc-js/build/src/call-stream.js:355:18\n at <anonymous>\n at process._tickDomainCallback (internal/process/next_tick.js:229:7)"
}

For anybody finding this question later. My challenge was solved by this answer https://github.com/googleapis/nodejs-speech/issues/10#issuecomment-415900469
const { google } = require('googleapis');
(async () => {
const auth = await google.auth.getClient({
scopes: ['https://www.googleapis.com/auth/cloud-platform']
});
const { data } = await google.speech('v1').operations.get({ auth, name: OPERATION_NAME });
console.log(data);
})();

Related

Error: No Contract deployed with name Ebay

Getting this error while testing my Ebay Contract
ITs An Ebay Smart Contract Where Products are being Auctioned
yarn run v1.22.15
warning package.json: No license field
$ "E:\Block Chain Projects\30_SMARTCONTRACTS.sol\A Way To Testing\node_modules\.bin\hardhat" test
Ebay Smart Contract
Upload Product function
This is deployer0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
1) "before each" hook for "if the base Price is less than 0 or invalid should revert"
0 passing (2s)
1 failing
1) Ebay Smart Contract
"before each" hook for "if the base Price is less than 0 or invalid should revert":
Error: No Contract deployed with name Ebay
at Object.getContract (node_modules\#nomiclabs\hardhat-ethers\src\internal\helpers.ts:447:11)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at Context.<anonymous> (test\Test.js:18:12)
error Command failed with exit code 1.
MY TEST.js
//it
//describe
//beforeEach
const { expect, assert } = require("chai");
const { ethers, getNamedAccounts } = require("hardhat");
describe("Ebay Smart Contract", async function() {
let Ebay;
let deployer;
const product = {
name: "CYCLE",
description: "gare cycles",
BasePrice: "5",
};
beforeEach(async () => {
deployer = (await getNamedAccounts()).deployer;
console.log("This is deployer" + deployer);
Ebay = await ethers.getContract("Ebay", deployer);
});
describe("Upload Product function", async function() {
it("if the base Price is less than 0 or invalid should revert", async function() {
expect(
Ebay.UploadProduct(product.name, product.description, product.BasePrice)
).to.be.revertedWith(Base_Price_cannot_be_Zero());
});
});
});
My deploy.js
const { ethers, deployments } = require("hardhat");
require("dotenv").config();
async function main() {
// const { deploy, log } = deployments;
//const { deployer } = await getNamedAccounts();
const Auction = await ethers.getContractFactory("Ebay");
const auction = await Auction.deploy();
await auction.deployed();
console.log(auction.address);
// const Auction = await deploy("Auctionbargain", {
// from: deployer,
// args: [],
// log: true,
// waitconfirmations: network.config.blockConfirmations || 1,
// });
//console.log(Auction.address);
//log("------------------------------------");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.log(error);
process.exit(1);
});
hardhatconfig.js
require("#nomicfoundation/hardhat-toolbox");
require("hardhat-deploy");
require("dotenv").config();
/** #type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: {
compilers: [{ version: "0.6.6" }, { version: "0.8.8" }],
},
networks: {
hardhat: {
chainId: 31337,
},
// goerli: {
// url: GOERLI_RPC_URL,
// accounts: [PRIVATE_KEY],
// chainId: 5,
// blockConfirmations: 6,
// },
},
namedAccounts: {
deployer: {
default: 0, // here this will by default take the first account as deployer
},
},
};
It was correctly deployed but gave error everytime i try to test it
I Tried using ABI in place of deployer in my test.js but it did give me the same error
Are you sure you deployed the contract on the same network on which you’re testing? it says:
Error: No Contract deployed with name Ebay
this can happen if you‘re testing on another network where the contract isn’t deployed at.
Also consider that the contract is really named Ebay. I can’t check that since you didn’t provide the solidity file.

How to test files and json data at the same time with jest?

I have a post request with express that upload a file and some data to the mongodb:
// Routes
Router.post('/api/training', validator(createVideoSchema, 'body'), uploadVideo, createVideoHandler);
// Route Handlers
async function createVideoHandler (req: Request, res: Response, next: NextFunction) {
try {
const dataToCreate = {
...req.body,
url: req.file?.path,
mimetype: req.file?.mimetype
};
const data = await service.create(dataToCreate);
response(req, res, data, 201);
} catch (error) {
next(error);
}
}
the body must be validate by joi using the following schema:
import Joi from 'joi';
const title = Joi.string().email().min(5).max(255);
const description = Joi.string().min(5).max(255);
const thumbnail = Joi.string().min(5).max(255);
const tags = Joi.array().items(Joi.string().min(5).max(100));
const createVideoSchema = Joi.object({
title: title.required(),
description: description.required(),
thumbnail: thumbnail.required(),
tags: tags.required(),
});
export { createVideoSchema };
Then I am creating a test to verify I am receiving a 201 status code:
it('should have a 201 status code', async () => {
const response = await request(app).post(route)
.set('Accept', 'application/json')
.field('title', data.title)
.field('description', data.description)
.field('thumbnail', data.thumbnail)
.field('tags', data.tags)
.attach('video', Buffer.from('video'), { filename: 'video.mp4' });
expect(response.status).toBe(201);
});
For some reason the validation middleware throws me a 400 error saying that the data is missing:
Error: "title" is required. "description" is required. "thumbnail" is required. "tags" is required
I tried to send the data using .set('Accept', 'multipart/form-data') but it throws me the same error.
I guess this error has to do with the way I send the data, but I don't fully understand.
You typically should not call a live API from a test. Instead you should mock the different possibly API response scenarios and be sure your code handles the different possibilities correctly. Ideally you'll also have a client class of some kind to place direct calls to your API inside a class that can easily be mocked.
For example, you could mock the endpoint response for valid data with something like:
export class VideoClient {
async createVideo(data) {
const response = await request(app).post(route) // Whatever url points to your API endpoint
.set('Accept', 'application/json')
.field('title', data.title)
.field('description', data.description)
.field('thumbnail', data.thumbnail)
.field('tags', data.tags)
.attach('video', Buffer.from('video'), { filename: 'video.mp4' });
if (response.status.ok) {
return { response, message: 'someGoodResponseMessage'};
}
return { response, message: 'someErrorOccurred' };
}
}
Then in your test you can mock your client call:
import { VideoClient } from './clients/VideoClient.js'; // or whatever path you saved your client to
const goodData = { someValidData: 'test' };
const badData = {someBadData: 'test' };
const goodResponse = {
response: { status: 201 },
message: 'someGoodResponseMessage'
}
const badResponse = {
response: { status: 400 },
message: 'someErrorOccurred'
}
it('should have a 201 status code', async () => {
VideoClient.createVideo = jest.fn().mockReturnValue(goodResponse);
const results = await VideoClient.createVideo(goodData);
expect(results.response.status).toBe(201);
expect(results.message).toEqual('someGoodResponseMessage');
});
it('should have a 400 status code', async () => {
VideoClient.createVideo = jest.fn().mockReturnValue(badResponse);
const results = await VideoClient.createVideo(badData);
expect(results.response.status).toBe(400);
expect(results.message).toEqual('someErrorOccurred');
});
This is by no means a working test or exhaustive example, but demonstrating the idea that you really should not call your API in your tests, but instead call mock implementations of your API to handle how your client code responds in different situations.

How can i get many details as possible about error using React Error boundry get error details?

Im tring to catch more details when error accuring.
when the error is accuring im using node api server to catch the error and save in log file.
i simulated a Network Error and tring to get many details as possible.
when i console.log the error in frontend im getting this:
withFormHandler.js:28 Uncaught Error: Error: Network Error
at Object.componentDidUpdate (withFormHandler.js:28)
...
but i cant send this information using my api.
all im getting in the server side is an empty object.
so how can i catch and send many details as possible about the error and write it to the log file?
this is my ErrorBoundry component:
class ErrorBoundary extends React.Component {
state = {
hasError: false,
error: { message: "", stack: "" },
info: { componentStack: "" },
};
static getDerivedStateFromError = (error) => {
return { hasError: true };
};
componentDidCatch = (error, info) => {
this.setState({ error, info });
axios
.get(`http://localhost:5001/api/logs/error`, {
params: {
error: error.message,
details: info,
// details:error ---> this is also not give me information i need
},
})
.catch(() => {});
};
render() {
const { hasError, error, info } = this.state;
const { children } = this.props;
return hasError ? <ErrorComponent message={error.message} /> : children;
}
}
this is the server side handle:
router.get("/error", (req, res) => {
const errorMessage = req.query.error;
const details = req.query.details; -----> return an empty object :(
const logFile = "./logs/debug.log";
if (errorMessage) {
let error = errorMessage + "\r\n" + details;
fs.appendFile(logFile, error, function (err) {
// callback or something
});
}
});

Mock multiple api call inside one function using Moxios

I am writing a test case for my service class. I want to mock multiple calls inside one function as I am making two API calls from one function. I tried following but it is not working
it('should get store info', async done => {
const store: any = DealersAPIFixture.generateStoreInfo();
moxios.wait(() => {
const request = moxios.requests.mostRecent();
request.respondWith({
status: 200,
response: store
});
const nextRequest = moxios.requests.at(1);
nextRequest.respondWith({
status: 200,
response: DealersAPIFixture.generateLocation()
});
});
const params = {
dealerId: store.dealerId,
storeId: store.storeId,
uid: 'h0pw1p20'
};
return DealerServices.retrieveStoreInfo(params).then((data: IStore) => {
const expectedOutput = DealersFixture.generateStoreInfo(data);
expect(data).toMatchObject(expectedOutput);
});
});
const nextRequest is always undefined
it throw error TypeError: Cannot read property 'respondWith' of undefined
here is my service class
static async retrieveStoreInfo(
queryParam: IStoreQueryString
): Promise<IStore> {
const res = await request(getDealerStoreParams(queryParam));
try {
const locationResponse = await graphQlRequest({
query: locationQuery,
variables: { storeId: res.data.storeId }
});
res.data['inventoryLocationCode'] =
locationResponse.data?.location?.inventoryLocationCode;
} catch (e) {
res.data['inventoryLocationCode'] = 'N/A';
}
return res.data;
}
Late for the party, but I had to resolve this same problem just today.
My (not ideal) solution is to use moxios.stubRequest for each request except for the last one. This solution is based on the fact that moxios.stubRequest pushes requests to moxios.requests, so, you'll be able to analyze all requests after responding to the last call.
The code will look something like this (considering you have 3 requests to do):
moxios.stubRequest("get-dealer-store-params", {
status: 200,
response: {
name: "Audi",
location: "Berlin",
}
});
moxios.stubRequest("graph-ql-request", {
status: 204,
});
moxios.wait(() => {
const lastRequest = moxios.requests.mostRecent();
lastRequest.respondWith({
status: 200,
response: {
isEverythingWentFine: true,
},
});
// Here you can analyze any request you want
// Assert getDealerStoreParams's request
const dealerStoreParamsRequest = moxios.requests.first();
expect(dealerStoreParamsRequest.config.headers.Accept).toBe("application/x-www-form-urlencoded");
// Assert graphQlRequest
const graphQlRequest = moxios.requests.get("POST", "graph-ql-request");
...
// Assert last request
expect(lastRequest.config.url).toBe("status");
});

Getting an error when subscribing a queue

My backend pushes messages to rabbitmq queue and I need to fetch those messages to display in the frontend part of the messages, since the messages have to be in specific order, I cannot use an asynchronous approach.
I have written this code
var open require("amqplib").connect("amqp://guest:guest#localhost:5682");
var queue = "developer";
export default {
name: 'Subsriber',
data: function() {
return {
selected: "",
services: [],
}
},
mounted() {
var url = "http://10.0.9.134:5060/services/scripts";
this.services = []; // empty the existing list first.
setTimeout(() => {
axios.get(url)
.then(response => {
this.services = response.data;
})
}, 2000)
open.then(function(conn){
return conn.createChannel();
}).then(function(ch){
return ch.assertQueue(queue).then(function(ok){
return ch.consume(queue, function(msg){
if (msg != null){
console.log(msg.content.toString());
}
});
});
});
}
but I get this error:
"Unhandled rejection TypeError: QS.unescape is not a function
openFrames#webpack-internal:///./node_modules/_amqplib#0.5.2#amqplib/lib/connect.js:50:1
connect#webpack-internal:///./node_modules/_amqplib#0.5.2#amqplib/lib/connect.js:145:14
connect/<#webpack-internal:///./node_modules/_amqplib#0.5.2#amqplib/channel_api.js:7:12
connect#webpack-internal:///./node_modules/_amqplib#0.5.2#amqplib/channel_api.js:6:10
#webpack-internal:///./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/SelectServices.vue:56:12
["./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/SelectServices.vue"]#http://10.0.9.134/app.js:1251:1
__webpack_require__#http://10.0.9.134/app.js:679:1
hotCreateRequire/fn#http://10.0.9.134/app.js:89:20
#webpack-internal:///./src/components/SelectServices.vue:1:148
["./src/components/SelectServices.vue"]#http://10.0.9.134/app.js:1804:1
__webpack_require__#http://10.0.9.134/app.js:679:1
hotCreateRequire/fn#http://10.0.9.134/app.js:89:20
#webpack-internal:///./src/router/index.js:4:85
["./src/router/index.js"]#http://10.0.9.134/app.js:1820:1
__webpack_require__#http://10.0.9.134/app.js:679:1
hotCreateRequire/fn#http://10.0.9.134/app.js:89:20
#webpack-internal:///./src/main.js:4:66
["./src/main.js"]#http://10.0.9.134/app.js:1812:1
__webpack_require__#http://10.0.9.134/app.js:679:1
hotCreateRequire/fn#http://10.9.0.134/app.js:89:20
[0]#http://10.9.1.147/app.js:1829:18
__webpack_require__#http://10.0.9.134/app.js:679:1
#http://10.9.0.134/app.js:725:18
#http://10.9.0.134/app.js:1:1"

Resources