the newbie coder
the newbie coder

Reputation: 682

Node.js - Firebase Cloud Functions batch write is not working

I am trying to get currency exchange rates from fixer.io (in JSON format) and store it into firestore using the firebase cloud functions. The code works great if I did not commit the batch, it is able to show the results into the console. But when I commit the batch, there is nothing being created in my firestore and there are no error logs shown in the console except for the usual Function executed, finished with status "ok"

Below is my Cloud Function's code. I have included an API key in the request method too, feel free to use it as I only use it for testing purposes

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

const firestore = functions.firestore;
const db = admin.firestore();

const FieldValue = require('firebase-admin').firestore.FieldValue;

const request = require('request');

exports.testCurrency = firestore
        .document('trigger/{docId}')
        .onUpdate((change, context) => {
            return request('http://data.fixer.io/api/latest?access_key=aeb14ea1a7db3bbf08edc96a41bd4be1', (error, response, body) => {
                if(error){
                    return console.log('error:', error);
                }

                body = JSON.parse(body);
                console.log('response: ', response.statusCode);

                var batch = db.batch();

                Object.keys(body["rates"]).forEach((key, index) => {
                                console.log(key,body["rates"][key]);
                                // key: the name of the object key
                                // index: index of key
                                var batchRef = db.collection('currencyRates').doc(key);
                                batch.set(batchRef, {
                                    base: body.base,
                                    code: key,
                                    value: body["rates"][key],
                                    dateCreated: FieldValue.serverTimestamp() 
                                });
                            });

                return batch.commit().then( () => {
                            return console.log("im done");
                        }).catch((err) => {
                            return console.log('Error batch: ', err);
                        });
            });
    });

This is the results in JSON format. The rates array's size is about 168 if it matters.

{
    success: true,
    timestamp: 1539162846,
    base: "EUR",
    date: "2018-10-10",
    rates: {
        AED: 4.21958,
        AFN: 86.890666,
        ALL: 125.212079,
        AMD: 555.643524,
        ANG: 2.029407,
        AOA: 348.895181,
        ARS: 42.90457,
        AUD: 1.619478,
        AWG: 2.068292,
        AZN: 1.955714,
        BAM: 1.953077,
        BBD: 2.288159,
        BDT: 96.49329,
        BGN: 1.955774,
        BHD: 0.433066,
        BIF: 2030.211654,
        BMD: 1.148732,
        BND: 1.619944,
        BOB: 7.900117,
        BRL: 4.269034,
        BSD: 1.143126,
        BTC: 0.000176,
        BTN: 85.26911,
        BWP: 12.46839,
        BYN: 2.462135,
        BYR: 22515.148904,
        BZD: 2.297751,
        CAD: 1.489098,
        CDF: 1866.689969,
        CHF: 1.14073,
        CLF: 0.025961,
        CLP: 781.999328,
        CNY: 7.951635,
        COP: 3515.235059,
        CRC: 671.686818,
        CUC: 1.148732,
        CUP: 30.4414,
        CVE: 110.879642,
        CZK: 25.839465,
        DJF: 204.152281,
        DKK: 7.46024,
        DOP: 57.019033,
        DZD: 136.351778,
        EGP: 20.59275,
        ERN: 17.230769,
        ETB: 31.762606,
        EUR: 1,
        FJD: 2.46248,
        FKP: 0.873014,
        GBP: 0.873927,
        GEL: 3.0154,
        GGP: 0.873866,
        GHS: 5.645042,
        GIP: 0.873123,
        GMD: 56.879486,
        GNF: 10343.241533,
        GTQ: 8.809053,
        GYD: 236.724948,
        HKD: 9.002495,
        HNL: 27.485141,
        HRK: 7.421727,
        HTG: 80.234922,
        HUF: 324.873057,
        IDR: 17489.331151,
        ILS: 4.163562,
        IMP: 0.873866,
        INR: 85.253156,
        IQD: 1364.17679,
        IRR: 48367.364525,
        ISK: 132.609588,
        JEP: 0.873866,
        JMD: 152.476977,
        JOD: 0.815388,
        JPY: 130.030675,
        KES: 116.079279,
        KGS: 79.626322,
        KHR: 4654.771655,
        KMF: 492.432692,
        KPW: 1033.875108,
        KRW: 1306.533994,
        KWD: 0.348762,
        KYD: 0.952753,
        KZT: 425.277826,
        LAK: 9754.698885,
        LBP: 1735.676925,
        LKR: 196.53612,
        LRD: 180.064096,
        LSL: 16.892084,
        LTL: 3.391907,
        LVL: 0.694857,
        LYD: 1.586976,
        MAD: 10.897331,
        MDL: 19.430783,
        MGA: 4015.335983,
        MKD: 61.577767,
        MMK: 1791.849588,
        MNT: 2946.506569,
        MOP: 9.22564,
        MRO: 410.097772,
        MUR: 39.701904,
        MVR: 17.702453,
        MWK: 835.353456,
        MXN: 21.915972,
        MYR: 4.77302,
        MZN: 69.463749,
        NAD: 16.909355,
        NGN: 416.162676,
        NIO: 36.701418,
        NOK: 9.464513,
        NPR: 136.021946,
        NZD: 1.778777,
        OMR: 0.442245,
        PAB: 1.143293,
        PEN: 3.82126,
        PGK: 3.839121,
        PHP: 62.253815,
        PKR: 147.026549,
        PLN: 4.307079,
        PYG: 6749.384482,
        QAR: 4.182653,
        RON: 4.663511,
        RSD: 118.365442,
        RUB: 76.049784,
        RWF: 1012.733695,
        SAR: 4.307918,
        SBD: 9.226628,
        SCR: 15.645159,
        SDG: 20.655924,
        SEK: 10.446081,
        SGD: 1.588583,
        SHP: 1.517356,
        SLL: 9591.913264,
        SOS: 667.413258,
        SRD: 8.567209,
        STD: 24504.701795,
        SVC: 10.00385,
        SYP: 591.597066,
        SZL: 17.114991,
        THB: 37.862491,
        TJS: 10.775738,
        TMT: 4.020562,
        TND: 3.260443,
        TOP: 2.638176,
        TRY: 7.025433,
        TTD: 7.705815,
        TWD: 35.617013,
        TZS: 2626.001928,
        UAH: 32.080682,
        UGX: 4336.463361,
        USD: 1.148732,
        UYU: 37.80484,
        UZS: 9353.378599,
        VEF: 285482.841016,
        VND: 26824.042963,
        VUV: 131.850501,
        WST: 3.039038,
        XAF: 655.064673,
        XAG: 0.080115,
        XAU: 0.000968,
        XCD: 3.104506,
        XDR: 0.825483,
        XOF: 654.949648,
        XPF: 119.089105,
        YER: 287.142825,
        ZAR: 16.841745,
        ZMK: 10339.970197,
        ZMW: 14.261535,
        ZWL: 370.299545
    }
}

UPDATE: my firebase account is currently on Blaze Plan (Pay as You Go) because I found a post on SO that says free plan won't allow 3rd party access

Upvotes: 3

Views: 1842

Answers (1)

Renaud Tarnec
Renaud Tarnec

Reputation: 83058

Your problem comes from the fact that a call with request does not return a promise, while in Cloud Functions triggered by background events (like .onUpdate() for Firestore) you must return a Promise. Watch this official video series for more details: https://firebase.google.com/docs/functions/video-series/ (in particular the 3 videos titled "Learn JavaScript Promises", which explain it very well).

So you need to use an interface wrapper for request, like request-promise.

The following modified code should work:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

const firestore = functions.firestore;
const db = admin.firestore();

const FieldValue = require('firebase-admin').firestore.FieldValue;

const request = require('request');
const rp = require('request-promise');

exports.testCurrency = firestore
        .document('trigger/{docId}')
        .onUpdate((change, context) => {

            var options = {
                url: 'http://data.fixer.io/api/latest?access_key=aeb14ea1a7db3bbf08edc96a41bd4be1',
                method: 'GET'
            };

            return rp(options)
            .then(body => {

                body = JSON.parse(body);

                var batch = db.batch();

                Object.keys(body["rates"]).forEach((key, index) => {
                            console.log(key,body["rates"][key]);
                            // key: the name of the object key
                            // index: index of key
                            var batchRef = db.collection('currencyRates').doc(key);
                            batch.set(batchRef, {
                                base: body.base,
                                code: key,
                                value: body["rates"][key],
                                dateCreated: FieldValue.serverTimestamp() 
                            });
                        });

                return batch.commit();

        });

    });

Upvotes: 6

Related Questions