Function execution took 60015 ms, finished with status: 'timeout' - node.js

This code is a Google cloud function node.js script that exports a function fsdb_sch which uses the node-schedule and firebase-admin. The script sets up a scheduled job that runs every day at midnight using the node-schedule module. The job reads values from a Firebase Realtime Database at the location All_machines/Generator using firebase-admin module, and then writes the same values to new locations within the same database.
The Firebase Realtime Database is accessed with the help of a service account which is stored in a JSON file, ./******************************-7878b7ca66.json.
But When I am running this code I am getting only this error in logs nothing else this error Function execution took 60015 ms, finished with status: 'timeout'. I have increase the time till 540s but function stop after 540s i have also increase the memory but nothing work. But the same code is running fine in my local system from pas few days without any errors.
this is my code :
const schedule = require('node-schedule');
const Admin = require("firebase-admin");
const { getDatabase } = require("firebase-admin/database");
const serviceAccount = require("./*********************************-7878b7ca66.json");
Admin.initializeApp({
credential: Admin.credential.cert(serviceAccount),
databaseURL: "https://****************************.firebasedatabase.app"
});
exports.fsdb_sch = (req, res) => {
const db = Admin.database();
const Db = getDatabase();
const ref = Db.ref("All_machines/Generator");
const Ref = db.ref("All_machines/Generator")
schedule.scheduleJob('0 0 * * *',() => {
ref.once('value', (snapshot) => {
snapshot.forEach((data) => {
ref.child(data.key).child('waterY').once('value', (snapshot) => {
let childref = Ref.child(data.key).child('waterYY');
childref.set(snapshot.val());
console.log(snapshot.val());
});
ref.child(data.key).child('waterT').once('value', (snapshot) => {
let childref = Ref.child(data.key).child('waterY');
childref.set(snapshot.val());
console.log(snapshot.val());
});
ref.child(data.key).child('compY').once('value', (snapshot) => {
let childref = Ref.child(data.key).child('compYY');
childref.set(snapshot.val());
console.log(snapshot.val());
});
ref.child(data.key).child('compT').once('value', (snapshot) => {
let childref = Ref.child(data.key).child('compY');
childref.set(snapshot.val());
console.log(snapshot.val());
});
});
}, (errorObject) => {
console.log('The read failed: ' + errorObject.name);
});
});
};
This is Package.json file
{
"name": "sample-http",
"version": "0.0.1",
"description": "Cloud Function for Schedular",
"scripts": {
"serve": "firebase emulators:start --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "16"
},
"main": "index.js",
"dependencies": {
"firebase-admin": "^11.4.1",
"firebase-functions": "^3.14.1",
"mqtt": "^4.3.7",
"node-schedule": "^2.1.0"
},
"devDependencies": {
"firebase-functions-test": "^0.2.0"
},
"private": true
}
And this is the folder structure
Logs:

Cloud functions have timeout, you should not use cloud functions for long running tasks.
You can use this guide to trigger your function using cloud scheduler instead.
scheduler will publish to a topic(just empty data) based on your cron expression
topic will trigger your cloud function, and execute required script.

Related

Cannot find module package.json with Electron + Strapi v4

I am experiencing a problem creating a boilerplate with Electron and Strapi CMS, with the Strapi v4 only.
A similar boilerplate already exist for Strapi v3 at the following url https://github.com/afdallismen/electron-strapi-boilerplate and it works fine.
So I made some changes and I made a similar one with Strapi v4: https://github.com/AsoStrife/Strapi-V4-Electron-Boilerplate
Here my two main files:
package.json:
{
"name": "Strapi-V4-Electron-Boilerplate",
"version": "1.0.0",
"description": "A minimal Electron application with Strapi v4",
"main": "main.js",
"scripts": {
"strapi-start": "strapi start",
"strapi-develop": "strapi develop",
"strapi-build": "strapi build",
"electron": "electron .",
"electron-build": "electron-builder",
"build": "strapi build && electron-builder"
},
"keywords": [
"Electron",
"Strapi",
"Boilerplate",
"CMS"
],
"author": "Andrea Corriga",
"license": "MIT",
"dependencies": {
"#strapi/plugin-i18n": "4.3.0",
"#strapi/plugin-users-permissions": "4.3.0",
"#strapi/strapi": "4.3.2",
"better-sqlite3": "7.4.6",
"electron-is-dev": "^2.0.0",
"electron-is-packaged": "^1.0.2"
},
"devDependencies": {
"electron": "^19.0.8",
"electron-builder": "^22.14.5"
},
"strapi": {
"uuid": "23376639-3e73-4487-812b-a57332ff6859"
},
"engines": {
"node": ">=12.x.x <=16.x.x",
"npm": ">=6.0.0"
}
}
and main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')
const Strapi = require('#strapi/strapi')
const isPackaged = require('electron-is-packaged')
const strapi = Strapi()
if (isPackaged) {
const fs = require('fs')
const path = require('path')
const appPath = path.join(app.getPath('home'), app.getName())
const requiredFolderPaths = {
database: path.join(appPath, 'database'),
public: path.join(appPath, 'public'),
uploads: path.join(appPath, 'public', 'uploads'),
}
Object.values(requiredFolderPaths).forEach((folderPath) => {
if (!fs.existsSync(folderPath)) {
fs.mkdirSync(folderPath, { recursive: true });
}
})
}
process.env.NODE_ENV = isPackaged ? 'production' : 'development';
process.env.BROWSER = 'none';
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
preload: path.join(__dirname, 'preload.js')
}
})
win.maximize()
win.webContents.openDevTools()
strapi
.start()
.then(() => {
win.loadURL('http://localhost:1337/admin');
//win.loadFile('index.html')
})
.catch((err) => {
console.error(err)
})
win.on('closed', () => {
app.quit();
})
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
So where's the problem?
If I run npm run electron it works perfectly, Electron opens correctly, with Strapi UI, a working DB and API accessible by localhost.
But if I run npm run build or npm run electron-build I generate a Strapi-V4-Electron-Boilerplate.exe but it doesn't work.
It gives me this error and I don't know how to debug. All dependencies are correct (I suppose, since with the npm run electron command everything works.
Has anyone experienced similar problems? Do you have any idea how to debug this problem to figure out what is not working?
Update 05/08/2022 [DD/MM/YYYY]
The solution is to change the strapi constructor
const strapi = Strapi({
appDir: `${__dirname}/`,
})
In Strapi v4 the parameter is appDir instead of dir in v3.
Once the app is built, if you try to run the executable (eg..exe) and the app crashes on startup you may need to copy and paste the .envfile inside the folder where the executable is located.
So if your .exe is located on ./dist/win-unpacked copy the .env-example into that folder and rename it in .env. This file follow the Strapi guideline. Check out strapi's documentation to learn more.

Why am I encountering an error when deploying a nodejs function in gcloud with a zip or directly with editor?

I want to realize cloud functions, I do it on vscode. I think I use all that is necessary to realize the cloud function.
To test this one I installed # google-cloud / storage and it works perfectly on my machine, however when I compress in zip to import it into GCP at deployment it gives me an error:
(Build failed: function.js does not exist; Error ID: 7485c5b6)
While I clearly indicate the entry point of my exports.backup function that I indicate in the entry point in GCP.
Here is the code I'm trying to run - something must be missing but I can't figure it out.
package.json:
{
"name": "export-mysql",
"version": "1.0.0",
"description": "create backup database production",
"main": "index.js",
"scripts": {
"backup": "functions-framework --target=backup"
},
"author": "",
"license": "ISC",
"dependencies": {
"chalk": "^4.1.2",
"dayjs": "^1.10.7",
"dotenv": "^10.0.0",
"googleapis": "^92.0.0",
"#google-cloud/functions-framework": "^2.1.0"
}
}
code:
const { google } = require("googleapis");
const sqlAdmin = google.sqladmin("v1beta4");
const dayjs = require("dayjs");
const chalk = require("chalk");
const dotenv = require("dotenv");
const log = console.log;
const error = console.error;
dotenv.config({ path: "./config/.env" });
let = respo = "";
authorize(function (authClient) {
const date = dayjs(Date.now()).format("YYYYMMDDHHmm");
var request = {
project: "project",
instance: "database-prod",
resource: {
exportContext: {
databases: ["database"],
fileType: "SQL",
kind: "sql#exportContext",
uri: `gs://backup-database-pop/backup-prod-${date}.gz`,
},
},
auth: authClient,
};
sqlAdmin.instances.export(request, function (err, response) {
if (err) {
error(chalk.yellow.bold(`Status: ${err.code}`));
log(chalk.red.bold(`Message: ${err.message}`));
return;
}
// TODO: Change code below to process the `response` object:
// log(chalk.yellow.bold(`Status: ${response.status}`));
log(chalk.greenBright.bold(`Database Exporter dans le bucket -> backup-database-pop fichier: backup-prod-${date}.sql`));
respo = `Database Exporter dans le bucket -> backup-database-pop fichier: backup-prod-${date}.sql`;
return respo;
// log.log(JSON.stringify(response, null, 2));
});
});
function authorize(callback) {
google.auth
.getClient({
scopes: ["https://www.googleapis.com/auth/cloud-platform"],
})
.then((client) => {
callback(client);
})
.catch((err) => {
error(chalk.red.bold("authentication failed: ", err));
});
}
exports.backup = (req, res) => {
res.end();
log(respo);
log("Function complete!");
};
And here is the structure of the folder that is zipped:
functionFolder
folder -> config/.env
index.js
package.json
package-lock.json
authorize.json
Here is the solution you have to select the files and compress them and not compress the folder

TypeError, admin.firestore(…).collection(…).doc(…).collection(…).doc(…).get.then is not a function

I'm trying to code a function that triggers when a user gets a new comment and sends a notification.Comments are stored in /Users/{user_id}/Notifications/{notification_id}. Users save their device notification tokens to /users/{userID}
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotif = functions.firestore.document('Users/{user_id}/Notifications/{notification_id}')
.onWrite((change,context) =>
{
const user_id = context.params.user_id;
const notification_id = context.params.notification_id;
return admin.firestore().collection('Users').document(user_id).collection('Notifications').document(notification_id).get().then(queryResult=>{
const from_user_id = queryResult.data().From;
const from_data = admin.firestore().collection('Users').document(from_user_id).get();
const to_data = admin.firestore().collection('Users').document(user_id).get();
return Promise.all([from_data, to_data]).then(result => {
const from_name = result[0].data().From;
const to_name = result[1].data().From;
console.log("FROM: " + from_name + "TO: " + to_name);
});
});
});
And here's the package.json file. Everything is up-to-date
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"dependencies": {
"firebase-admin": "^6.4.0",
"firebase-functions": "^2.1.0"
},
"private": true
}
Firebase gives the following error:
TypeError: admin.firestore(...).collection(...).document is not a function
at exports.sendNotif.functions.firestore.document.onWrite (/user_code/index.js:13:50)
at cloudFunctionNewSignature (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:105:23)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:135:20)
at /var/tmp/worker/worker.js:768:24
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
admin.firestore().collection(...) returns a CollectionReference object. As you can see from the linked API docs, there is no method called document() on that. But there is a doc() method. Use that instead.

Cannot read property 'parameters' of undefined while passing Context - Actions on Google

Currently I am trying to develop an action.
I am trying to achieve to reuse an intent. Concretely said, it means that the Assistant shall give me the first three items of a list and if I ask for more, then it should give me the next three items of the list.
I implemented the logic, which is locally working but sadly I always got the first three items from the list. Therefore i tried using a context, where I want to pass the index as a parameter and here i am running into the problem. The cloud function logs always gives me:
Cannot read property 'parameters' of undefined.
I am using dialog v2 api and the actions on Google sdk. Following link provides an example how to implement the context and I don't see a big difference there. https://developers.google.com/actions/reference/nodejsv2/overview
The code written for it looks like this:
app.intent('Default Welcome Intent', conv => {
conv.ask('Welcome.')
const lifespan = 100;
const parameters = {
index: 0,
};
conv.contexts.set('movieCtx', lifespan, parameters);
});
app.intent('New Cinema Movies Intent', async conv => {
let movieCtx = conv.contexts.get('movieCtx');
let index = movieCtx.parameters[index]
let movieRepository = new MovieRepository();
movieRepository.index = index;
await movieRepository.fetchNextTitle(3).then(function(titles) {
movieCtx.parameters[index] = movieRepository.index;
conv.ask('The 3 movies are:' + titles.join(', '))
return true;
}).catch(function(err) {
console.log(err);
return false;
});
})
My dependencies:
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"dependencies": {
"actions-on-google": "^2.5.0",
"firebase-admin": "~6.0.0",
"firebase-functions": "^2.0.3",
"pg": "^7.7.1"
},
"devDependencies": {
"eslint": "^4.12.0",
"eslint-plugin-promise": "^3.6.0"
},
"private": true
}
Update:
I also tried to change the following lines but also that couldn't help me:
const parameters = {
movieIndex: 0,
};
let index = movieCtx.parameters['movieIndex']
The line
let index = movieCtx.parameters[index]
Should probably be
let index = movieCtx.parameters['index']
(You don't have index defined previous to that, so it is trying to get the reference of undefined, which isn't valid.)
I was able to find the answer!
const {dialogflow} = require('actions-on-google');
const functions = require('firebase-functions');
const MovieRepository = require('./PostgreSQL/MovieRepository');
let movieRepository = new MovieRepository();
const app = dialogflow({debug: true});
const AppContexts = {
NUMBER: 'number',
}
app.intent('Default Welcome Intent', (conv) => {
const lifespan = 10;
const parameters = {
movieIndex: 0,
};
conv.contexts.set(AppContexts.NUMBER, lifespan, parameters);
conv.ask('Welcome!')
});
app.intent('New Cinema Movies Intent', async (conv) => {
const movieCtx = conv.contexts.get(AppContexts.NUMBER);
await movieRepository.fetchNextTitle(3).then(function(titles) {
movieCtx.parameters.movieIndex = movieRepository.index;
conv.ask('The 3 movie titles are: ' + titles.join(', '));
return true;
}).catch(function(err) {
console.log(err);
return false;
});
})
app.intent('Default Fallback Intent', conv => {
conv.ask('Sorry. Can you repeat?')
})
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
As you can see you have to create the AppContext above the intents. Somhow weird but important is that you apply
NUMBER: 'number'
to the context, otherwise you get an undefined context again. And to access your parameters you just need to append your the value of your parameter like this:
movieCtx.parameters.movieIndex

Node, firebase functions Property 'map' does not exist on type 'Promise<QuerySnapshot>

Firstly that does not helps me: property map does not exist and importing 'rxjs' does nork either
just testing using typescript with my functions and using "async" and "await" keywords for some reason I'm getting error when trying to use map here is my code(btw if the way I retriving data from firestore using "await" is incorrect I would be very greatfull if someone correct me) -could not find alot of examples that uses typescript/functions/firestore):
import * as functions from 'firebase-functions';
import * as admin from "firebase-admin";
admin.initializeApp(functions.config().firebase);
let db = admin.firestore();
export const helloWorld = functions.https.onRequest(
async (request, response) => {
try {
let t = await getEmployees()
response.send("yes");
} catch (e) {
response.send('no')
}
});
async function getEmployees(): Promise<any> {
try {
const f = await db.collection('companies').get().map(value => {
let id = value.id
return id;
})
} catch (e) {
return e;
}
}
typescript Version 2.8.3
package.json:
{
"name": "functions",
"scripts": {
"lint": "tslint --project tsconfig.json",
"build": "tsc",
"serve": "npm run build && firebase serve --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"main": "lib/index.js",
"dependencies": {
"firebase-admin": "^5.12.0",
"firebase-functions": "^1.0.1"
},
"devDependencies": {
"tslint": "^5.8.0",
"typescript": "2.8.3"
},
"private": true
}
await will be applied over the result of map, you are essentially calling :
const f = await (db.collection('companies').get().map(...))
You want to call map on the result of awaiting get, and you should add parenthesis to tell the compiler this is what you want tot do. Also you are probably looking for the docs property on the snapshot (which returns the results of the query)
const f = (await db.collection('companies').get()).docs.map(...)

Resources