{"id":20135552,"url":"https://github.com/raisely/airblast","last_synced_at":"2025-09-15T08:06:41.071Z","repository":{"id":52061938,"uuid":"155951407","full_name":"raisely/airblast","owner":"raisely","description":"Robust cloud function job queuing and processing","archived":false,"fork":false,"pushed_at":"2022-12-08T04:30:31.000Z","size":513,"stargazers_count":2,"open_issues_count":7,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-02T22:41:37.167Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/raisely.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-03T04:54:59.000Z","updated_at":"2021-09-28T19:00:40.000Z","dependencies_parsed_at":"2023-01-24T10:25:13.346Z","dependency_job_id":null,"html_url":"https://github.com/raisely/airblast","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/raisely/airblast","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raisely%2Fairblast","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raisely%2Fairblast/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raisely%2Fairblast/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raisely%2Fairblast/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/raisely","download_url":"https://codeload.github.com/raisely/airblast/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raisely%2Fairblast/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275225879,"owners_count":25427009,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-15T02:00:09.272Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T21:15:32.467Z","updated_at":"2025-09-15T08:06:41.046Z","avatar_url":"https://github.com/raisely.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Airblast provides a simple framework to get cloud function jobs with retries up and\nrunning quickly so you can focus on building your jobs with minimal effort on\ninteracting with cloud infrastructure.\n\nAirblast handles dealing with pubub, express and datastore and you just handle\nprocessing the data.\n\nThe framework allows for building controllers that send jobs to one another for processing\nso you can logically breakup your background processing by logical concerns.\n\nSee the [samples](/samples) for examples of setting up simple controllers\n\nExample of job chains\n\n```javascript\nclass JobController extends AirblastController {\n  // Will return 400 if someone tries to post an invalid payload\n  validate({ data }) {\n    if (!data.about) {\n      throw new this.AppError(400, 'validation', 'Data must contain about attribute');\n    }\n  }\n\n  // Send the job to the email and airtable controller for processing\n  async process({ key }) {\n    return Promise.all([\n      // Pass the key of this record to the other controllers\n      this.controllers.email.enqueue({ key }),\n      this.controllers.airtable.enqueue({ key }),      \n    ])\n  }\n}\n\nclass EmailController extends AirblastController {\n  async process({ data }) {\n    // Load the record that was passed in\n    const payload = await this.load(data.key);\n    sendEmail({\n      to: 'admin@myco.example',\n      subject: 'Job received',\n      body: `The job is about ${data.about}`\n    });\n  }\n}\n\nclass AirtableController extends AirblastController {\n  async process({ data }) {\n    const payload = await this.load(data.key);\n    airtables.insert(payload);\n  }\n}\n```\n\nThat's it, once you've written your process function,\nyou've written cloud functions that are ready to deploy!\nSee the [sample](/sample) directory for scripts\nto deploy them.\n\n\n## Setting up for deployment\n\n1. Install gcloud command line\n\n```sh\ngcloud auth login\ngcloud config set project \u003cyour project id\u003e\n# List available zones to deploy functions\ngcloud functions regions list\ngcloud config set functions/region \u003cpreferred region\u003e\n# If you are also deploying the retry cron server, you will\n# probably want to set the default app engine zone to the same\ngcloud compute project-info add-metadata --metadata google-compute-default-region=\u003cpreferred region\u003e\n# Re-run gcloud init to make use of your new defaults\ngcloud init\n```\n\n\n## Testing\n\nMost of the time you can test your controller simply by running\n`controller.process(body)`\nbut if you need to test the webhook endpoint with authorization and \nvalidation, there is a helper to help you:\n\n```javascript\nconst runController = require('airblast/test/runController');\n\nawait runController(new MyController(), {\n  body: { my: 'value' },\n});\n```\n\nOptions and default values that you can pass to \n\n```\n{\n  // The controller function to execute (defaults to the function that receives and routes\n  // the http requests, usuall you don't need to change this)\n  function: 'http',\n  // Mock the enqueue (avoids the need for datastore \u0026 pubsub emulators)\n  mockEnqueue: true,\n  // Throw an error if the response status is not 200\n  throwOnError: true,\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraisely%2Fairblast","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fraisely%2Fairblast","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraisely%2Fairblast/lists"}