Облачная функция Firebase возвращает ошибку 304 и затем перезапускается - PullRequest
7 голосов
/ 08 марта 2019

Я застрял на этом в течение нескольких месяцев. Я удалил некоторые мелкие детали из функции, но ничего важного. У меня есть эта облачная функция https, которая завершает сеанс, а затем использует endTime и startTime для вычисления bill, который затем возвращается клиенту.

startTime извлекается из базы данных пожарной базы в реальном времени (которую поместила туда функция запуска сеанса).

Мой фрагмент кода:

exports.endSession = functions.https.onRequest(async (req, res) => {
    console.log("endSession() called.")
    if(req.method == 'GET'){
        bid = req.query.bid
        session_cost = req.query.sessioncost
    }else{
        bid = req.body.bid
        session_cost = req.body.sessioncost
    }

start_time_ref = admin.database().ref("/online_sessions/").child(bid).child("start_time")
start_time_snapshot = await start_time_ref.once('value')

console.log("start_time_snapshot: "+start_time_snapshot.val())

start_time_snapshot = moment(start_time_snapshot.val(), 'dddd MMMM Do YYYY HH:mm:ss Z');
endDateTime = getDateTime()

console.log("startTime: " + start_time_snapshot.toString())
console.log("endTime: " + endDateTime.toString())
hour_difference = getHourDifference(start_time_snapshot, endDateTime)

bill = ride_cost * Math.ceil(hour_difference)
console.log("bill: "+bill)

var s_phone
sSessionlinks_ref = admin.database().ref('/sSessionlinks/')
sSessionlinks_snapshot = await sSessionlinks_ref.once('value')

sSessionlinks_snapshot.forEach((sid)=>{
    if(sid.val() == bid){
        s_phone = sid.key
    }
})

s_fcm_token_ref = admin.database().ref("/s/").child(s_phone).child("FCM")
s_fcm_token_snapshot = await s_fcm_token_ref.once('value')

try{ // telling another client that session has ended.
    await admin.messaging().send({
        data: {
            type: "sessionCompleted",
            bill: bill.toString()
        },
        token: s_fcm_token_snapshot.val() 
    })
}catch(error){

}

//deleting this session from online sessions
online_session_ref = admin.database().ref('/online_sessions/').child(bid)
await online_session_ref.remove()

//puting this session as available
available_session_ref = admin.database().ref('/available_sessions/')
json = {}
json[bid] = s_phone
await available_session_ref.update(json) // session made available


res.status(200).send(bill.toString())
// here it *sometimes* returns 304 and then restarts but since i've already removed online_session_ref I cannot get startTime again because its removed with online_sessions so it fails.
    // return
})

Когда его впервые вызвали. Он выполняет все вычисления правильно, но отвечает 304. Таким образом (я думаю, что клиент) повторно отправляет запрос, и функция вызывается снова, но поскольку сеанс уничтожен, он не может вычислить startTime.

Почему при первом вызове, даже если все вычисления выполнены правильно, возвращается значение 304, а не 200? Эта проблема не случается все время. Обычно это происходит, когда эта функция вызывается через долгое время, но я не уверен в этом. Я не знаю, что вызывает это.

Вспомогательные функции, которые я использовал:

function getHourDifference(s, e){
    return moment.duration(e.diff(s)).asHours()
}


function getDateTime(){
    d = moment.utc().utcOffset('+0530')
    return d
}

Когда функция заканчивается в первый раз, полезная нагрузка текста составляет Function execution took 794 ms, finished with status code 304

Когда он запускается во второй раз (где он не может получить startTime, потому что он был удален при первом запуске. Во-первых, не должно быть второго запуска.), Текст полезной нагрузки равен Function execution took 234 ms, finished with status code 200 (его 200 но верните NaN, потому что он не может делать вычисления без startTime.

EDIT: Как некоторые из вас попросили меня рассказать, как вызывается функция:

Это вызывается из Android-приложения, используя Volley. Параметры гарантированы, чтобы не быть нулем. Сегмент кода для вызова этой функции:

    // Setting the button's listeners.
    endSessionButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

                progressDialog = new SweetAlertDialog(getContext(), SweetAlertDialog.PROGRESS_TYPE);
                progressDialog.getProgressHelper().setBarColor(Color.parseColor("#A5DC86"));
                progressDialog.setTitleText("Ending session...");

                AlertDialog endDialog = new AlertDialog.Builder(getContext()).create();
                endDialog.setTitle("End Session?");

                Log.e("sessioncost", String.valueOf(session_cost));

                endDialog.setButton(Dialog.BUTTON_POSITIVE, "Yes", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        progressDialog.show();
                        // Instantiate the RequestQueue.
                        RequestQueue queue = Volley.newRequestQueue(getContext());

                        String url = "https://us-central1-something-something.cloudfunctions.net/endSession?bid=" + bid + "&sessioncost=" + session_cost;
                        Log.e("end sesion button", url);
                        // Request a string response from the provided URL.
                        StringRequest endSessionRequest = new StringRequest(Request.Method.GET, url,
                                new Response.Listener<String>() {
                                    @Override
                                    public void onResponse(final String response) {
                                        progressDialog.dismiss();
                                        Toast.makeText(getContext(), "Session Completed", Toast.LENGTH_LONG).show();

                                        progressDialog = new SweetAlertDialog(getContext(), SweetAlertDialog.SUCCESS_TYPE);
                                        progressDialog.getProgressHelper().setBarColor(Color.parseColor("#A5DC86"));
                                        progressDialog.setTitleText("Session Completed: Bill");
                                        progressDialog.setContentText("Please pay ?" + response + " to s.");
                                        progressDialog.setCancelable(false);
                                        progressDialog.show();

                                        changeState('1');

                                        bill_in_paise = Float.parseFloat(response) * 100;
                                        Log.e("bill", bill_in_paise.toString());
                                        progressDialog.setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
                                            @Override
                                            public void onClick(SweetAlertDialog sweetAlertDialog) {

                                                sweetAlertDialog.dismiss();
                                                Intent intent = new Intent(getContext(), PaymentActivity.class);
                                                intent.putExtra("amt", bill_in_paise.toString());
                                                startActivityForResult(intent, REQUEST_CODE);
                                            }
                                        });


                                    }
                                }, new Response.ErrorListener() {
                            @Override
                            public void onErrorResponse(VolleyError error) {
                                Toast.makeText(getContext(), error.toString(), Toast.LENGTH_LONG).show();
                            }// onErrorResnponse - END
                        });

                        // Add the request to the RequestQueue. Cuz volley is asyc af.
                        queue.add(endSessionRequest);
                        // VOLLEY REQUEST - END
                    }
                });
                endDialog.setButton(Dialog.BUTTON_NEGATIVE, "No", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(getContext(), "Session not cancelled.  " + which, Toast.LENGTH_LONG).show();
                    }
                });

                endDialog.show();


            }

        }
    }); // endSessionButton onclick - end

ОБНОВЛЕНИЕ: @tuledev помог исправить 304 с обходным путем, но проблема все еще здесь. Даже когда код состояния равен 200, облачная функция снова вызывается, и я получаю счет NaN. На данный момент я не знаю, что вызывает это.

1 Ответ

2 голосов
/ 18 марта 2019

Статус 304 приходит, потому что ответ такой же, как и предыдущий.Облачные ответы Firebase 304 и клиент получит кэшированные данные.

Для предотвращения статуса 304 мы можем вернуть значение + uid счета или что-то еще, чтобы сделать ответ отличным от предыдущего.

Как мы уже говорили с ОП, 304 решена, но проблема все еще здесь.Так что я думаю, что проблема исходит от клиентской стороны.

Надеюсь, что кто-нибудь может ПОМОЧЬ ему.

Редактировать: OP здесь, я изменил код клиента на использование okhttp вместо volley и после тестирования на 2дни все кажется в порядке.Ответ Туледева исправил 304, но даже после 200 проблема сохранялась.Просто используйте охтпп вместо залпа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...