<commit_before>// Copyright (c) 2017 Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Cloud Functions for Firebase is used to process session reservation requests.
//
// Clients are permitted to write requests into the queue. RTDB Rules are used
// to restrict clients to writing one request at a time.
//
// Each written request triggers a function that processes the request. Once the
// request is processed it is removed from the queue allowing clients to submit
// more requests.

var functions = require('firebase-functions');
var google = require('googleapis');

// firebase-admin module is used to perform RTDB updates while processing
// reservation requests.
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

// Amount of time (in millis) before the start of a session required for
// reservations to be allowed. 30 minutes.
const RES_CUT_OFF = 1800000;

const PATH_SESSIONS = 'sessions';
const PATH_RESERVATIONS = 'reservations';
const PATH_RESULTS = 'results';
const PATH_STATUS = 'status';
const PATH_SEATS = 'seats';
const PATH_ACTION = 'action';
const PATH_SESSION = 'session';
const PATH_QUEUE = 'queue';
const PATH_PROMO_QUEUE = 'promo_queue';
const PATH_LAST_STATUS_CHANGED = 'last_status_changed';
const PATH_EVENTS = 'events';

const REQUEST_ID = 'request_id';

const ACTION_RESERVE = 'reserve';
const ACTION_RETURN = 'return';

const STATUS_GRANTED = 'granted';
const STATUS_WAITING = 'waiting';
const STATUS_RETURNED = 'returned';

const RESERVATION_RESERVED = 'reserved';
const RESERVATION_DENIED_NO_SPACE = 'denied no space';
const RESERVATION_CLOSED = 'reservations closed';
const RESERVATION_RETURNED = 'returned';
const RESERVATION_RETURN_FAILED = 'unable to complete return';
const RESERVATION_FAILED = 'unable to complete reservation';
const RESERVATION_DENIED_CLASHING = 'denied other session clashes';

const RESULT_RESERVED = 'reserved';
const RESULT_RESERVED_NO_SPACE = 'reserve_denied_space';
const RESULT_RESERVED_CUTOFF = 'reserve_denied_cutoff';
const RESULT_RESERVED_CLASH = 'reserve_denied_clash';
const RESULT_RESERVED_FAILED = 'reserve_failed';

const RESULT_RETURNED = 'returned';
const RESULT_RETURNED_CUTOFF = 'return_denied_cutoff';
const RESULT_RETURNED_FAILED = 'return_failed';

const USERDATA_DISCOVERY_URL = 'USERDATA_DISCOVERY_URL';

const GOOGLE_PROVIDER_ID = 'google.com';

/**
 * Function to process "promotion from waitlist" requests. When a granted seat
 * is returned and there are attendees on the waitlist a request is written
 * to the promo_queue path.
 *
 * This function assumes that request are written in the form:
 * /promo_queue/<session id>/<timestamp>: true
 */
exports.processPromotions = functions.database.ref('/promo_queue/{sid}/{rid}').onWrite(event => {
  if (!event.data || !event.data.val() || !event.eventId) {
    return;
  }

  let eid = event.eventId;
  // Event IDs contain slashes and when written to the DB they cause children
  // using replace here to use dashes instead of slashes.
  eid = eid.replace(/\//g, "-");

  isNewEvent(eid).then(function(newEvent) {
    if (newEvent) {
      const sid = event.params.sid;
      const rid = event.params.rid;
      return promoteFromWaitlist(sid).then(function (result) {
        console.log('attendee was promoted from waitlist of session ' + sid
            + ' ended with result: ' + result);
        return getPromoQueueReference(sid).child(rid).set({});
      }).catch(function (error) {
        console.error(error);
        return getPromoQueueReference(sid).child(rid).set({});
      });
    } else {
      // Do nothing, this is a duplicate event.
      console.log("duplicate event found: " + eid);
    }
  });
});

/**
 * This function listens to the request queue. When a request is written to the
 * queue by a client, this function executes.
 *
 * This function assumes that requests are submitted of the form:
 * /queue/<user id> : {
 *   session_id: <session id>,
 *   action: <reserve or return>,
 *   request_id: <timestamp>
 * }
 */
exports.processRequest = functions.database.ref('/queue/{uid}').onWrite(event => {
  if (!event.data || !event.data.val() || !event.eventId) {
    return;
  }

  let eid = event.eventId;
  // Event IDs contain slashes and when written to the DB they cause children
  // using replace here to use dashes instead of slashes.
  eid = eid.replace(/\//g, "-");

  isNewEvent(eid).then(function(newEvent) {
    if (newEvent) {
      const request = event.data.val();
      const action = request[PATH_ACTION];
      const sid = request[PATH_SESSION];
      const rid = request[REQUEST_ID];
      const uid = event.params.uid;

      return process(uid, sid, rid, action).then(function(result) {
        console.log(action + ' with uid: ' + uid + ' and sid: ' + sid
            + ' ended with result: ' + result);
        return getQueueReference(uid).set({});
      }).catch(function(error) {
        console.error(error);
        return getQueueReference(uid).set({});
      });
    } else {
      // Do nothing, this is a duplicate event.
      console.log("duplicate event found: " + eid);
    }
  });<commit_msg>Return in functions!!!<commit_after>// Copyright (c) 2017 Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Cloud Functions for Firebase is used to process session reservation requests.
//
// Clients are permitted to write requests into the queue. RTDB Rules are used
// to restrict clients to writing one request at a time.
//
// Each written request triggers a function that processes the request. Once the
// request is processed it is removed from the queue allowing clients to submit
// more requests.

var functions = require('firebase-functions');
var google = require('googleapis');

// firebase-admin module is used to perform RTDB updates while processing
// reservation requests.
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

// Amount of time (in millis) before the start of a session required for
// reservations to be allowed. 30 minutes.
const RES_CUT_OFF = 1800000;

const PATH_SESSIONS = 'sessions';
const PATH_RESERVATIONS = 'reservations';
const PATH_RESULTS = 'results';
const PATH_STATUS = 'status';
const PATH_SEATS = 'seats';
const PATH_ACTION = 'action';
const PATH_SESSION = 'session';
const PATH_QUEUE = 'queue';
const PATH_PROMO_QUEUE = 'promo_queue';
const PATH_LAST_STATUS_CHANGED = 'last_status_changed';
const PATH_EVENTS = 'events';

const REQUEST_ID = 'request_id';

const ACTION_RESERVE = 'reserve';
const ACTION_RETURN = 'return';

const STATUS_GRANTED = 'granted';
const STATUS_WAITING = 'waiting';
const STATUS_RETURNED = 'returned';

const RESERVATION_RESERVED = 'reserved';
const RESERVATION_DENIED_NO_SPACE = 'denied no space';
const RESERVATION_CLOSED = 'reservations closed';
const RESERVATION_RETURNED = 'returned';
const RESERVATION_RETURN_FAILED = 'unable to complete return';
const RESERVATION_FAILED = 'unable to complete reservation';
const RESERVATION_DENIED_CLASHING = 'denied other session clashes';

const RESULT_RESERVED = 'reserved';
const RESULT_RESERVED_NO_SPACE = 'reserve_denied_space';
const RESULT_RESERVED_CUTOFF = 'reserve_denied_cutoff';
const RESULT_RESERVED_CLASH = 'reserve_denied_clash';
const RESULT_RESERVED_FAILED = 'reserve_failed';

const RESULT_RETURNED = 'returned';
const RESULT_RETURNED_CUTOFF = 'return_denied_cutoff';
const RESULT_RETURNED_FAILED = 'return_failed';

const USERDATA_DISCOVERY_URL = 'USERDATA_DISCOVERY_URL';

const GOOGLE_PROVIDER_ID = 'google.com';

/**
 * Function to process "promotion from waitlist" requests. When a granted seat
 * is returned and there are attendees on the waitlist a request is written
 * to the promo_queue path.
 *
 * This function assumes that request are written in the form:
 * /promo_queue/<session id>/<timestamp>: true
 */
exports.processPromotions = functions.database.ref('/promo_queue/{sid}/{rid}').onWrite(event => {
  if (!event.data || !event.data.val() || !event.eventId) {
    return;
  }

  let eid = event.eventId;
  // Event IDs contain slashes and when written to the DB they cause children
  // using replace here to use dashes instead of slashes.
  eid = eid.replace(/\//g, "-");

  return isNewEvent(eid).then(function(newEvent) {
    if (newEvent) {
      const sid = event.params.sid;
      const rid = event.params.rid;
      return promoteFromWaitlist(sid).then(function (result) {
        console.log('attendee was promoted from waitlist of session ' + sid
            + ' ended with result: ' + result);
        return getPromoQueueReference(sid).child(rid).set({});
      }).catch(function (error) {
        console.error(error);
        return getPromoQueueReference(sid).child(rid).set({});
      });
    } else {
      // Do nothing, this is a duplicate event.
      console.log("duplicate event found: " + eid);
    }
  });
});

/**
 * This function listens to the request queue. When a request is written to the
 * queue by a client, this function executes.
 *
 * This function assumes that requests are submitted of the form:
 * /queue/<user id> : {
 *   session_id: <session id>,
 *   action: <reserve or return>,
 *   request_id: <timestamp>
 * }
 */
exports.processRequest = functions.database.ref('/queue/{uid}').onWrite(event => {
  if (!event.data || !event.data.val() || !event.eventId) {
    return;
  }

  let eid = event.eventId;
  // Event IDs contain slashes and when written to the DB they cause children
  // using replace here to use dashes instead of slashes.
  eid = eid.replace(/\//g, "-");

  return isNewEvent(eid).then(function(newEvent) {
    if (newEvent) {
      const request = event.data.val();
      const action = request[PATH_ACTION];
      const sid = request[PATH_SESSION];
      const rid = request[REQUEST_ID];
      const uid = event.params.uid;

      return process(uid, sid, rid, action).then(function(result) {
        console.log(action + ' with uid: ' + uid + ' and sid: ' + sid
            + ' ended with result: ' + result);
        return getQueueReference(uid).set({});
      }).catch(function(error) {
        console.error(error);
        return getQueueReference(uid).set({});
      });
    } else {
      // Do nothing, this is a duplicate event.
      console.log("duplicate event found: " + eid);
    }
  });
{'fraction_non_alphanumeric': 0.11162174105170128, 'fraction_numerical': 0.0030048608042421566, 'mean_word_length': 3.8587376556462, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3385748', 'n_tokens_mistral': 3436, 'n_tokens_neox': 3327, 'n_words': 1102}