0

I am trying to set up a firebase cloud function that regularly makes an api call to the Feedly API.

However, it is not working and I'm not sure why. Here is the code:

const functions = require('firebase-functions')
const express = require('express')
const fetch = require('node-fetch')
const admin = require('firebase-admin')

admin.initializeApp()
const db = admin.firestore()

const app = express()

exports.getNewsArticles = functions.pubsub
  .schedule('every 5 minutes')
  .onRun(() => {
    app.get('/feedly', async (request, response) => {

      const apiUrl = `https://cloud.feedly.com/v3/streams/contents?streamId=user/[USER_ID_NUMBER]/category/global.all&count=100&ranked=newest&newThan=300000`

      const fetchResponse = await fetch(apiUrl, {
        headers: {
          Authorization: `Bearer ${functions.config().feedly.access}`
        }
      })

      const json = await fetchResponse.json()

      json.items.forEach(item => {
        db.collection('news').add({
          status: 'pending',
          author: item.author || '',
          content: item.content || '',
          published: item.published || '',
          summary: item.summary || '',
          title: item.title || '',
        })
      })
    })
  })

Any idea what I need to do to get this to work?

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
Moshe
  • 6,011
  • 16
  • 60
  • 112
  • You can check this answer https://stackoverflow.com/questions/35737708/how-to-run-cron-job-with-firebase/56063698#56063698 – Gastón Saillén Dec 15 '19 at 17:32
  • What is not working? What have you tried? What errors (if any are produced)? What symptoms? – Kolban Dec 15 '19 at 17:35
  • Next time please don't repost the same [question](https://stackoverflow.com/questions/59346125/google-cloud-functions-cron-job-not-working), but instead edit your original question (there's a link right under it) to include the additional information. – Frank van Puffelen Dec 15 '19 at 17:50
  • @FrankvanPuffelen I did NOT repost the same question. That question is asking about why I cannot run a scheduled cloud function with the `firebase serve` command. This other question is asking about how to run a scheduled cloud function with an api call. I still would like an answer to my other question (even though this one was properly answered). – Moshe Dec 15 '19 at 18:39
  • Woops, good point. I think I might have misclicked on the same question of yours twice. Sorry about that. I reopened the [your other question](https://stackoverflow.com/questions/59346125/google-cloud-functions-cron-job-not-working?noredirect=1), and will probably answer as what you're trying to do is unfortunately not (yet) possible. – Frank van Puffelen Dec 15 '19 at 21:02

1 Answers1

4

There are potentially three problems in your Cloud Function:

1. You are mixing up the code for Schedule Functions with the one of HTTPS Functions

Have a look at the doc for Schedule Functions and HTTPS Functions. In a Schedule Function, you should not use app.get() and just do, for example:

exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun((context) => {
  console.log('This will be run every 5 minutes!');
  return null;
});

2. You must return a Promise (or a value)

You must return a Promise (or a value) in your Cloud Function, to indicate to the platform that the Cloud Function has completed. In case the tasks in the Cloud Function are synchronous you can just return a a value, e.g. return null; as shown in the example above. In case one or more tasks are asynchronous you must return a Promise.

So, in your case you need to use Promise.all() as follows, since you are executing several (asynchronous) writes in parallel:

exports.getNewsArticles = functions.pubsub
  .schedule('every 5 minutes')
  .onRun((context) => {

      const apiUrl = `https://cloud.feedly.com/v3/streams/contents?streamId=user/[USER_ID_NUMBER]/category/global.all&count=100&ranked=newest&newThan=300000`

      const fetchResponse = await fetch(apiUrl, {
        headers: {
          Authorization: `Bearer ${functions.config().feedly.access}`
        }
      })

      const json = await fetchResponse.json()

      const promises = [];

      json.items.forEach(item => {
        promises.push(
          db.collection('news').add({
            status: 'pending',
            author: item.author || '',
            content: item.content || '',
            published: item.published || '',
            summary: item.summary || '',
            title: item.title || '',
          }))
      })

      return Promise.all(promises)
  })

3. You may need to upgrade your pricing plan

You need to be on the "Flame" or "Blaze" pricing plan.

As a matter of fact, the free "Spark" plan "allows outbound network requests only to Google-owned services". See https://firebase.google.com/pricing/ (hover your mouse on the question mark situated after the "Cloud Functions" title)

Since the Feedly API is not a Google-owned service, you may need to switch to the "Flame" or "Blaze" plan.

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
  • 2
    Thanks -- that was a great answer (very detailed and to the point). Much appreciated. Just for the record, I had already signed up for the Blaze pricing plan. My question was simply on how to combine a scheduled cloud function with an outside api call. Again, much thanks. – Moshe Dec 15 '19 at 18:37