Giter VIP home page Giter VIP logo

vets-api's Introduction

Vets API

This project provides common APIs for applications that live on VA.gov (formerly vets.gov APIs).

Yard Docs License: CC0-1.0

Build Status

VA.gov Platform Documentation

API Docs

For frontend, see vets-website and vets-content repos.

Base setup

  1. Clone the vets-api repo:

    git clone https://github.com/department-of-veterans-affairs/vets-api.git
  2. Setup key & cert for localhost authentication to ID.me:

    • Create a folder in your vets-api directory:

      mkdir config/certs
      touch config/certs/vetsgov-localhost.crt
      touch config/certs/vetsgov-localhost.key
    • Copy example configuration file:

      cp config/settings.local.yml.example config/settings.local.yml
    • Edit config/settings.local.yml to disable signed authentication requests:

      # settings.local.yml
      saml:
        authn_requests_signed: false
  3. If you are developing features that need Sidekiq Enterprise, you must have access to the va.gov-team-sensitive repo and install the sidekiq enterprise license

    Sidekiq Enterprise is used for worker rate limiting and additional reliability in production and requires a license be configured on your development machine. If you do not have a license configured, the open source version of Sidekiq will be installed instead. This is not an issue unless you are specifically developing features that need Sidekiq Enterprise.

    DO NOT commit local Gemfile modifications that remove the sidekiq-ent and sidekiq-pro gems.

  4. Developers who work with vets-api daily tend to prefer the native setup because they don't have to deal with the abstraction of docker-compose while those who would to spend less time on getting started prefer the docker setup. Docker is also useful when it's necessary to have a setup as close to production as possible. Finally, it's possible to use a hybrid setup where you run vets-api natively, but run the Postgres and Redis dependencies in docker.

Running the app

Configuration

Vets API is configured with Config. The default configuration is contained in settings.yml. To customize your setup, you can create a config/settings.local.yml file with configuration specific to your needs. For example, to configure Redis and PostgreSQL (PostGIS is required), place something like this in that file:

database_url: postgis://pg_host:9999/custom_db

redis:
  host: redis_host
  port: 9999

This is also where you will place any other customizations, such as API tokens or certificate paths.

Config settings that vary in value depending on the deployment environment will also need to be set appropriately for each environment in the relevant devops (Private Repo) configurations (dev-, staging-, and prod-settings.local.yml.j2).

Some examples of configuration that will need to be added to these files are:

  • API keys/tokens
  • 3rd party service hostnames, ports, and certificates/keys.
  • Betamocks settings

Optional application configuration

The following features require additional configuration, click for details.

To mock one or more of the above services see Betamocks

Vets API will still run in a limited capacity without configuring any of these features, and will run the unit tests successfully.

Deployment instructions

Jenkins deploys vets-api upon each merge to master:

http://jenkins.vfs.va.gov/job/testing/job/vets-api/job/master/

Each deploy is available here:

https://dev-api.va.gov/v0/status

Additional deployment details can be found here:

additional deployment details

API request key formatting

When sending HTTP requests use the X-Key-Inflection request header to specify which case your client wants to use. Valid cases are camel, dash, and snake. For example if you set X-Key-Inflection: camel then you can use camelCase keys in your JSON request body and you will get back data with camelCase keys in the response body. If the header is not provided then the server will expect snake_case keys in the request body and output snake_case in the response.

Versions

The version of Ruby and gem dependencies (including Rails) used are defined in the included Gemfile. The currently used versions of gems are maintained with Bundler and stored in the Gemfile.lock.

Version Policy

The goal is to have vets-api use supported versions of gems and Ruby, which is often the latest. However the versions are generally updated as need or availability arise. If you need a newer version of a gem, please submit a pull-request marked as draft with just the gem updated and passing tests.

Not a member of the repository and want to be added?

  • If you're on a VA.gov Platform team, contact your Program Manager.
  • If you're on a VFS team, you must complete Platform Orientation to be added to this repository. This includes completing your Platform Orientation ticket(s) in GitHub.

vets-api's People

Contributors

aherzberg avatar ajmagdub avatar annaswims avatar ateal avatar bastosmichael avatar bosawt avatar caseywilliams avatar cilestin avatar dependabot[bot] avatar dillo avatar edmangimelli avatar elleeb avatar ericboehs avatar holdenhinkle avatar hpjaj avatar jperk51 avatar jw81 avatar kpethtel avatar kreek avatar lihanli avatar lindseysaari avatar markolson avatar nathanbwright avatar omgitsbillryan avatar patrickvinograd avatar rileyanderson avatar saneshark avatar smluthi avatar stiehlrod avatar thrillberg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vets-api's Issues

Documentation for external service integrations

The DevOps team needs brief documentation around services the application integrates with so we can better configure our monitoring. This should include at least a brief description of the service, what components of the vets-api depend on that service, expected potential failures, what behaviors to expect from our app during failures, and if available, how to test the health of the service independently of application actions.

This documentation will also be useful for incident response.

Filtering for SM

Marc and I drew this up on the board yesterday and he will provide more details on how filtering will work in the API documentation he is writing in #87

Define facility locator choice act data format

See https://github.com/department-of-veterans-affairs/kudos-team/blob/master/FacilityLocator/Facility%20Data%20Samples.md for a description of the underlying data.
See #134 for related discussion of VA health facility data.

Like #134 we need to define the output of REST queries for choice act (non-VA provider) data.

Whereas the VA facility GIS data returns facilities (i.e. hospitals/clinic) and their services, the Choice act GIS data returns individual providers (i.e doctors). The data is de-normalized, so a given doctor may have multiple records for each of the specialty they provide at a location, and may have multiple records for each of the locations that they work from. So we need to do some level of aggregation - at least combining all of a doctor's specialties at a given location, and possibly combining all providers at a given location so we can display a map pin.

It does not appear that there is any stable unique identifier that lets us aggregate all the providers and services at a single location (i.e. at a map pin). The UniqueProviderCode identifies a doctor but may give multiple locations. So it may not make sense to provide a "get single record by ID" API operation for getting details - all operations on this may effectively be queries by lat/long. But we need to analyze the data to see how accurate the lat/long data is.

Ensure No External Requests in Initializers

Normally webmock would catch any external requests, but if they occur in an initializer prior to WebMock.disable_net_connect! they will actually be made.

https://github.com/department-of-veterans-affairs/vets-api/blob/master/config/initializers/saml_settings.rb is one such example.

If the IDP is down, this will result in a build breaking or test environments failing, we need to have a more robust mechanism for handling these issues and we should always make sure they happen at an application runtime level, not at initialization.

One solution would be to move the saml_settings into a service class that is invoked at controller level, and have it be redis backed -- the metadata would be loaded from redis first, if it is not available it will make the request and cache it to redis for future requests. We should set the timeout window to something short -- like 5-10 seconds, and we should rescue exception with our own custom exception class to ensure that the error is logged, JSON is returned informing of the issue. In this case, it would likely be a 500 level error.

Another solution would be to hardcode the metadata, if this is not subject to change that is. We could then just load it as an ENV var.

Authn, Authz, and API.

@robbiethegeek asked me to write up some thoughts on the API architecture and how it relates to AuthN and AuthZ. So here goes...

For AuthN, there are 2 pieces:

  1. ID.me session
  2. www.vets.gov session

For AuthZ, there are 2 pieces:

  1. Delegated Authorization server/generator
  2. api.vets.gov authorization consumer/validator

For the API business logic, there are at least 2 pieces:

  1. Database access to the "Veteran Profile".
  2. Access to the "task queue."

The above is generic architecture that should be true regardless of underlying technology choice. The only axioms are (a) www.vets.gov and api.vets.gov are 2 different origins (b) id.me is providing identity.

AuthN (authentication)

Input: (maybe) User's username/password
Endpoints: Whatever the authnrequest endpoint in id.me is and https://www.vets.gov/auth/saml-acs-url
Output: A session on the www.vet.gov origin with identity info that's valid for the session and used by the authz step below.

For (1) id.me is handling the login session. We should verify how this session behaves. 3 user scenarios matter:

  1. User has no session with id.me and a SAML bounce is initiated from vets.gov. Here, user should be prompted from a password and sent back to vets.gov. If vets.gov session is destroyed (eg www.vets.gov cookies cleared)...and user visits id.me, ensure password is repromtped. The easy architecture mistake here is id.me retains the login session so the user just silently gets regarnted a SAML Assertion.
  2. User has existing session with id.me (eg, via id.me wallet) and SAML session is initiated from vets.gov. It's unclear what the right behavior here is. By default, I expect the user will just log into vets.gov silently without a password prompt. It's unclear that if we clear the vets.gov session if they'd log out of id.me too. This is the tricky scenario that we need to hammer out with their product team ASAP as it is possibly an architecture level change for their service.
  3. User has existing session with www.vets.gov and logs out of www.vets.gov. Expected behavior is if they hit login, they will be reprompted for a password. Again, interactions id.me session properties need to be exercised like in the above.

Note that the ACS URL should be on www.vets.gov and NOT api.vets.gov. This is because your login session that has your identity is best located along with the webapps itself. If you host on api.vets.gov, this gets a bit harder as you are now creating an additional (unnecessary) cross-origin information share for no real reason.

In the simplest setup, https://www.vets.gov/auth/saml-acs-url should set a secure https cookie that holds whatever login or identity info is necessary for the app.

If you want to get more complicated, you could store that info client-side only with HTML5 sessionStorage or localStorage...but in all cases, the information is bound to the www.vets.gov origin and not the api.vets.gov origin which is conceptually cleaner because api.vets.gov remains stateless and because you're not poking holes in the origin security boundary between api.vets.gov and www.vets.gov.

For a login session, I think cookies or localStorage are the best ways to store the info. Using server-side sessions feels overkill and places an unnecessarily scaling dependency on the server having a coherent database across all webserver instances (imagine we get a new east region but TIC still bounces people between E/W every 30 seconds via DNS round-robin...you'd have a crazy hard time keeping the session DB consistent).

sessionStorage is tempting, but not quite right here because of the session forking semantics when a new window is created. If you right-click "open new tab" on a link, the two sessionStorages are now forked and diverge. If you open a new tab and navigate back to www.vets.gov, there is no way to access the sessionStorage since the objective is to give tab isolation meaning the user will behave as if they are logged out. sessionStorage is probably great for transient app state...not so much for login.

For storage of the identity attributes, I would just dump it in a secure cookie unless you have a strong reason to keep the browser from seeing the data...but that's weird since you're basically asking a user not to attack their own PII.

So in summary:

  • www.vets.gov creates AuthNRequest to id.me
  • id.me returns SAML Assertion with identity attributes to www.vets.gov/auth/saml-acs-url
  • an actual app server running on www.vets.gov receives the Assertion, decrypts it, and creates a session on www.vets.gov with the login credentials and identity attributes. This identity attributes should be made available to the javascript context of the react apps but the login session should be protected as usual via secure cookies.
  • This login session will then be used in the AuthZ step to generate the delegated authorization for the API server. This is why the login session must exist and be bound to www.vets.gov and not api.vets.gov.

AuthZ (Authorization)

Input: A valid login session, likely in a cookie.
Endpoints: https://www.vets.gov/auth/oauth2
Output: An OAuth2 access token that can be used in the Authorization header for request to api.vets.gov

NOTE: if you do not have api.vets.gov DNS stood-up yet, I highly suggest creating a heroku app that reverse proxies the API server so you can correctly simulate the API server being on a different origin! If you do not do this, you're gonna run into all sorts of fun with rails sessions colliding. Spinning up a reverse proxy hack should cost you like 1/2 a day but ensure you are developing against the right security contraints.

Rant... There's been a lot of argument about JWT vs Oauth2. It doesn't matter which you use, but I think it's silly to use JWT cause the world uses OAuth2, JWT does not solve the same problem, and the OAuth2 detractors are...well...just the same few people who write shrill blogs. We've spent more time arguing about this than it'd take to write up both prototypes. You can wire up an OAuth2 provider in about 1-2 days and the consumer libraries are tested. Just use OAuth2. It'll keep the API easily compatible with mobile ecosystems and frameworks as well which is a longer term goal. Or if there is really strong resistance still (there shouldn't be. stop arguing for JWT. Oauth2 setup is not complicated...the libraries abstracted ita ll), at least stop discussing whether or not to use it and stand up some real authorization server asap. The devs need to learn how to pass these things around and debug authorization issues which is being blocked by pushing off standing up a real one. If there's a question about this...ask how many devs are thinking about CORS problems or writing wrappers for fetch in react? If the answer isn't everyone, then there's learning to be had that's being blocked.
...End-Rant

For the MVP, create 1 "scope" (this is just a string you put in the configs for the server and client libraries) named https://www.vets.gov/oauth/scopes/all or something that is just "all access" for a user. You can create more restricted scopes (eg 'https://www.vets.gov/oauth/scopes/rx-refill', 'https://www.vets.gov/oauth/scopes/secure-messaging') later if there is some meaningful separation. But for now, just one uber access scope makes sense.

After the server is stood up with a configured scope, write it up to a webapp to get an access token after having logged in. Assuming the user has a valid www.vets.gov session and that the authorization server running doorkeeper has access to this session (hint: use the same app server for the saml acs_url as authorization server so they can share the session secret)

Assuming https://github.com/doorkeeper-gem/doorkeeper gem, I think the following is accurate:

  1. Client app uses OAuth2 library to generate a authz request for https://www.vets.gov/oauth/scopes/allto https://www.vets.gov/auth/oauth2/authorize
  2. https://www.vets.gov/auth/oauth2/authorize server notices "it is a first party auth" (make the controller skip prompting the user to click "authorize this app" if the request is coming from the registered www.vets.gov application... this flow is useful if a non-vets.gov source like a mobile app wants to use api.vets.gov). This controller now becomes just a check that we have a www.vets.gov session and is otherwise a no-op.
  3. https://www.vets.gov/auth/oauth2/authorize returns the authorization code (aka refresh token) to the app. This is given to the oauth-2 client library which will at some point do another post that exchanges the authorization token for an actual "access token" that will be passed to `api.vets.gov.
  4. Client App has all information needed to create API requests to api.vets.gov. We likely want to create a wrapper around fetch that annotates the access tokens from above onto all API requests in an Authorization: header.

On the api-server side, add in the right authorization checks with doorkeeper to validate the tokens for the target endpoints.

API business logic

Input: POST/GET to api.vets.gov with Oauth2 Authorization token.
Endpoints: api.vets.gov/*
Output: Some JSON response and maybe side-effects to backend systems.

This is the easiest portion. The React app should be making API request with just the access token. api.vets.gov will have to associate in the backend the oauth2 token with the veteran profile. After validation of the access token is completed and the associated profile is found, the authn and authz technologies are done. Now it's just standard business logic checks to do the real authorization.

Nested facility service data

@patrickvinograd VHA data (which is what we have available via the VA API right now) has services available at facilities. these services look flat in the data returned from the VA's API, however they are actually nested in that some of the services are major categories (service level 1 = SL1) and some are minor categories (Service level 2 = SL2) within major categories. An example of this is that DiagnosticServices is an SL1 while ImagingAndRadiology and LabServices are SL2's that fit under DiagnosticServices.

I believe that instead of returning something like (this is just a subset of what's returned for a facility):

{
    "DiagnosticServices": "YES",
    "ImagingAndRadiology": "YES",
    "LabServices": "NO",
}

We should do something like:

{
    "DiagnosticServices": {
        "ImagingAndRadiology": true,
    }
}

Two changes here:
(1) is that it ImagingAndRadiology is nested under DiagnosticServices, so the front end knows they are associated
(2) is that only the services that are available at the facility show up, rather than having a whole lot of "NO"s in there.
Note, the "true" there at the end still feels weird to me and I'm sure there is a better way of doing, but I just wanted to get this concept overall out there first.

Attachments for SM

Need to implement all routes and functionality related to attachments

Define facility locator VA health facility format

Using this issue to come to agreement about facility locator data format. Limiting discussion for now to VA health facilities. Will file a separate issue for Choice Act provider data, and likely a separate issue for VA benefits and cemetery facilities.

See baseline data available from GIS data source in https://github.com/department-of-veterans-affairs/kudos-team/blob/master/FacilityLocator/Facility%20Data%20Samples.md
See nesting discussion in #126

Here is a baseline object:

{ "attributes":
{"OBJECTID":1510,
"FacilityDataDate":"8-19-2016",
"OutpatientServicesDataDate":1472428800000,
"StationID":539,
"VisnID":20,
"StationNumber":"648A4",
"StationName":"Portland VA Medical Center-Vancouver",
"CommonStationName":"Portland-Vancouver",
"CocClassification":"VA Medical Center (VAMC)",
"CocClassificationAttribute":"Firm",
"Building":null,
"Street":"1601 East 4th Plain Boulevard",
"Suite":null,
"City":"Vancouver",
"State":"WA",
"Zip":"98661",
"Zip4":"3753",
"MainPhone":"360-759-1901 x",
"MainFax":"360-690-0864 x",
"AfterHoursPhone":"360-696-4061 x",
"PatientAdvocatePhone":"503-273-5308 x",
"EnrollmentCoordinatorPhone":"503-273-5069 x",
"PharmacyPhone":"503-273-5183 x",
"Monday":"730AM-430PM",
"Tuesday":"730AM-630PM",
"Wednesday":"730AM-430PM",
"Thursday":"730AM-430PM",
"Friday":"730AM-430PM",
"Saturday":"800AM-1000AM",
"Sunday":"-",
"Latitude":45.63941626,
"Longitude":-122.65528736,
"Audiology":"YES",
"ComplementaryAlternativeMed":"NO",
"DentalServices":"YES",
"DiagnosticServices":"YES",
"ImagingAndRadiology":"YES",
"LabServices":"NO",
"EmergencyDept":"NO",
"EyeCare":"YES",
"MentalHealthCare":"YES",
"OutpatientMHCare":"YES",
"OutpatientSpecMHCare":"YES",
"VocationalAssistance":"YES",
"OutpatientMedicalSpecialty":"NO",
"AllergyAndImmunology":"NO",
"CardiologyCareServices":"NO",
"DermatologyCareServices":"NO",
"Diabetes":"NO",
"Dialysis":"NO",
"Endocrinology":"NO",
"Gastroenterology":"NO",
"Hematology":"NO",
"InfectiousDisease":"NO",
"InternalMedicine":"NO",
"Nephrology":"NO",
"Neurology":"NO",
"Oncology":"NO",
"PulmonaryRespiratoryDisease":"NO",
"Rheumatology":"NO",
"SleepMedicine":"NO",
"OutpatientSurgicalSpecialty":"YES",
"CardiacSurgery":"NO",
"ColoRectalSurgery":"NO",
"ENT":"NO",
"GeneralSurgery":"NO",
"Gynecology":"NO",
"Neurosurgery":"NO",
"Orthopedics":"NO",
"PainManagement":"NO",
"PlasticSurgery":"NO",
"Podiatry":"YES",
"ThoracicSurgery":"NO",
"Urology":"NO",
"VascularSurgery":"NO",
"PrimaryCare":"YES",
"Rehabilitation":"YES",
"UrgentCare":"NO",
"WellnessAndPreventativeCare":"YES"
},
"geometry":{"x":-122.65530186353662,"y":45.63942173397186}
}

Proposed format is as follows:

  • Omitting fields: OBJECTID, FacilityDataDate, OutpatientServicesDataDate,CocClassificationAttribute
  • The "Latitude,Longitude" fields are returned in preference to the GIS "geometry" fields.
  • Key names generally simplified and changed to lowercase.
  • "StationID" -> "id"
  • "VisnID" -> "visn_id"
  • "StationName" -> "name"
  • "CocClassification" -> "classification"
  • Address fields nested under "address"
  • Phone fields nested under "phone"
  • Hours fields nested under "hours"
  • Services nested hierarchically under "services" as described in #126
  • Service type keys are not simplified/lowercased, they are kept exactly as-is in case they are referenced elsewhere.
{ 
  "id":539,
  "visn_id":20,
  "name":"Portland VA Medical Center-Vancouver",
  "classification":"VA Medical Center (VAMC)",
  "address": {
    "building":null,
    "street":"1601 East 4th Plain Boulevard",
    "suite":null,
    "city":"Vancouver",
    "state":"WA",
    "zip":"98661",
    "zip4":"3753"
  },
  "phone": {
    "main":"360-759-1901 x",
    "fax":"360-690-0864 x",
    "after_hours":"360-696-4061 x",
    "patient_advocate":"503-273-5308 x",
    "enrollment_coordinator":"503-273-5069 x",
    "pharmacy":"503-273-5183 x",
  },
  "hours": {
    "Monday":"730AM-430PM",
    "Tuesday":"730AM-630PM",
    "Wednesday":"730AM-430PM",
    "Thursday":"730AM-430PM",
    "Friday":"730AM-430PM",
    "Saturday":"800AM-1000AM",
    "Sunday":"-",
  },
  "services": {
    "Audiology": [],
    "DentalServices": [],
    "DiagnosticServices": ["ImagingAndRadiology"],
    "EyeCare": [],
    "MentalHealthCare": ["OutpatientMHCare", "OutpatientSpecMHCare", "VocationalAssistance"]
    "OutpatientSurgicalSpecialty": [],
    "PrimaryCare": [],
    "Rehabilitation": [],
    "WellnessAndPreventativeCare": []
  },
  "lat":45.63941626,
  "long":-122.65528736
}

Open issues:

  • Whether keys "Common Station Name" and "Station Number" are useful pieces of information.

Sorting for SM

I believe this will be needed just for /folders/:id/messages on sentDate, subject, and from

Pagination

Making everything that is a collection into one; will make sorting/filtering easier as well.

Olive Branch is preventing rails console from starting.

Traced error to this line in application.rb:
config.middleware.use "OliveBranch::Middleware"

The error:

/Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/actionpack-4.2.7.1/lib/action_dispatch/middleware/stack.rb:112:in `push': can't modify frozen Array (RuntimeError)
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/actionpack-4.2.7.1/lib/action_dispatch/middleware/stack.rb:112:in 'use'
           from /Users/v/Dsva/vets-api/config/application.rb:43:in '<class:Application>'
           from /Users/v/Dsva/vets-api/config/application.rb:18:in '<module:VetsAPI>'
           from /Users/v/Dsva/vets-api/config/application.rb:17:in '<top (required)>'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:274:in 'require'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:274:in 'block in require'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:240:in 'load_dependency'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:274:in 'require'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/railties-4.2.7.1/lib/rails/commands/commands_tasks.rb:141:in 'require_application_and_environment!'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/railties-4.2.7.1/lib/rails/commands/commands_tasks.rb:67:in 'console'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/railties-4.2.7.1/lib/rails/commands/commands_tasks.rb:39:in 'run_command!'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/railties-4.2.7.1/lib/rails/commands.rb:17:in '<top (required)>'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:274:in 'require'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:274:in 'block in require'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:240:in 'load_dependency'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:274:in 'require'
           from /Users/v/Dsva/vets-api/bin/rails:10:in '<top (required)>'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:268:in 'load'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:268:in 'block in load'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:240:in 'load_dependency'
           from /Users/v/.rvm/gems/ruby-2.3.0@sm-api/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:268:in 'load'
           from /Users/v/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in 'require'
           from /Users/v/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in 'require'
           from -e:1:in '<main>'

Create configuration for Education Regions

Spool files are broken up to group submissions to different regions based on the school the person is applying for. I think we're submitting 4 spool files a day, but need to verify.

Circuit breakers for external service integrations

In addition to timeouts from #74 , we should evaluate implementing circuit breakers for each of the application's external service integrations.

Our application has the potential to send more traffic to these systems than they may expect, and if they're down or under high load, the ability to back off and allow them to recover could mean improved overall uptime for our systems.

Timeouts for external service integrations

The DevOps team has configured monitoring for high average request latency from this application, and will work to integrate more metrics for individual services in the future. We've noticed average latency over 5 minute intervals is around ~1.5 seconds with considerable variability (up to ~40s and often between 10 and 30s).

To prevent false alarms and to better understand the application health and performance characteristics we should implement explicit timeouts around external services that this application interacts with. This also has the benefit of providing the customer a more consistent experience, since we'll be more explicitly defining the failure case and providing better feedback for things that take longer than expected or may be down.

The values for these timeouts should be based on the SLAs for the corresponding services.

Deleting a folder

Does the folder have to be empty? If yes, what is the error returned if you try to delete a folder and it isn't empty?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.