Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/hex/credo-1.7.10
Browse files Browse the repository at this point in the history
  • Loading branch information
KaylaBrady authored Nov 8, 2024
2 parents 2b00d5f + 587b798 commit 962f78b
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 28 deletions.
94 changes: 67 additions & 27 deletions load_testing/locustfile.py
Original file line number Diff line number Diff line change
@@ -1,85 +1,118 @@
import datetime
import random
from hashlib import sha256
from zoneinfo import ZoneInfo

import requests
from locust import HttpUser, between, events, task

from phoenix_channel import PhoenixChannel, PhoenixChannelUser

all_stop_ids: list[str] = list(map(lambda stop: stop["id"],requests.get(
all_station_ids: list[str] = list(map(lambda stop: stop["id"], requests.get(
"https://api-v3.mbta.com/stops",
{"fields[stop]": "latitude,longitude", "filter[location_type]": "0,1"},
{"fields[stop]": "id", "filter[location_type]": "1"},
).json()["data"]))

rail_stop_ids: list[str] = list(map(lambda stop: stop["id"], requests.get(
standalone_bus_stop_ids: list[str] = list(map(lambda stop: stop["id"],
filter(lambda stop: stop["relationships"]["parent_station"]["data"] is None, requests.get(
"https://api-v3.mbta.com/stops",
{"fields[stop]": "id", "filter[location_type]": "0", "filter[route_type]": "0,1"},
).json()["data"]))
{"fields[stop]": "id", "filter[location_type]": "0", "filter[route_type]": "3"},
).json()["data"])))

cr_stop_ids: list[str] = list(map(lambda stop: stop["id"], requests.get(
"https://api-v3.mbta.com/stops",
{"fields[stop]": "id", "filter[location_type]": "0", "filter[route_type]": "2"},
).json()["data"]))
all_stations_and_bus = all_station_ids + standalone_bus_stop_ids

bus_stop_ids: list[str] = list(map(lambda stop: stop["id"], requests.get(
"https://api-v3.mbta.com/stops",
{"fields[stop]": "id", "filter[location_type]": "0", "filter[route_type]": "3"},
).json()["data"]))

all_routes: list[dict] = requests.get(
"https://api-v3.mbta.com/routes",
{},
).json()["data"]

initial_global_headers = {}
initial_rail_headers = {}


@events.test_start.add_listener
def on_init(environment, **_kwargs):
# Assume some % of users have already loaded global data before.
# Fetch global + rail data once from target host to use as baseline etag headers for newly spawned users
host = environment.host
global initial_global_headers
global initial_rail_headers

initial_global_response = requests.get(f"{host}/api/global")
initial_global_headers = {}
if initial_global_response.status_code == 200:
initial_global_headers = {"if-none-match": sha256(initial_global_response.text.encode()).hexdigest()}

initial_rail_response = requests.get(f"{host}/api/shapes/map-friendly/rail")
initial_rail_headers = {}
if initial_rail_response.status_code == 200:
initial_rail_headers = {"if-none-match": sha256(initial_rail_response.text.encode()).hexdigest()}


@events.init_command_line_parser.add_listener
def _(parser):
parser.add_argument("--api-key", type=str, env_var="V3_API_KEY", default="", help="API Key for the V3 API. Set to avoid rate limiting.")

class MobileAppUser(HttpUser, PhoenixChannelUser):
wait_time = between(5, 20)
wait_time = between(5, 60)
socket_path = "/socket"

prob_reset_initial_load = 0.02
prob_reset_nearby_stops = 0.3
prob_filtered_stop_details = 0.76
prob_already_loaded_global = 0.8
prob_station = 0.6

location: dict | None = None
stop_id: str | None = None
nearby_stop_ids: list[str] | None = None
alerts_channel: PhoenixChannel | None = None
predictions_channel: PhoenixChannel | None = None
vehicles_channel: PhoenixChannel | None = None
did_initial_load = False
global_headers: dict = {}
rail_headers: dict = {}
v3_api_headers: dict = {}



v3_api_headers: dict = {}

def on_start(self):
self.v3_api_headers = {"x-api-key" : self.environment.parsed_options.api_key}

if random.random() < self.prob_already_loaded_global:
self.global_headers = initial_global_headers
self.rail_headers = initial_rail_headers

self.app_reload()

@task(1)
def app_reload(self):
self.client.get("/api/global")
self.client.get("/api/shapes/map-friendly/rail")
global_response = self.client.get("/api/global", headers=self.global_headers)
if global_response.status_code == 200:
self.global_headers = {"if-none-match": sha256(global_response.text.encode()).hexdigest()}

rail_response = self.client.get("/api/shapes/map-friendly/rail", headers=self.rail_headers)
if rail_response.status_code == 200:
self.rail_headers = {"if-none-match": sha256(rail_response.text.encode()).hexdigest()}

if self.alerts_channel is not None:
self.alerts_channel.leave()
self.alerts_channel = None

self.alerts_channel = self.socket.channel("alerts")
self.alerts_channel.join()

self.did_initial_load = True

def fetch_schedules_for_stops(self, stop_ids):
self.client.get(f'/api/schedules?stop_ids={stop_ids}&date_time={datetime.datetime.now().astimezone(ZoneInfo("America/New_York")).replace(microsecond=0).isoformat()}' , name="/api/schedules",)


@task(10)
def nearby_transit(self):
nearby_rail_ids = random.sample(rail_stop_ids, random.randint(2,8))
nearby_cr_ids = random.sample(cr_stop_ids, random.randint(0,14))
nearby_bus_ids = random.sample(bus_stop_ids, random.randint(0,14))
nearby_station_ids = random.sample(all_station_ids, random.randint(2,5))
nearby_bus_ids = random.sample(standalone_bus_stop_ids, random.randint(0,10))

self.nearby_stop_ids = nearby_rail_ids + nearby_cr_ids + nearby_bus_ids
self.nearby_stop_ids = nearby_station_ids + nearby_bus_ids
if (
self.predictions_channel is not None
and random.random() < self.prob_reset_nearby_stops
Expand All @@ -92,12 +125,19 @@ def nearby_transit(self):
f'predictions:stops:v2:{nearby_stops_concat}'
)
self.predictions_channel.join()

self.fetch_schedules_for_stops(self.nearby_stop_ids)



@task(5)
def stop_details(self):
self.stop_id = random.choice(all_stop_ids)
self.client.get(f'/api/schedules?stop_ids={self.stop_id}&date_time={datetime.datetime.now().astimezone(ZoneInfo("America/New_York")).replace(microsecond=0).isoformat()}' , name="/api/schedules",)
if random.random() < self.prob_station:
self.stop_id = random.choice(all_station_ids)
else:
self.stop_id = random.choice(standalone_bus_stop_ids)

self.fetch_schedules_for_stops([self.stop_id])
self.client.get(f'/api/stop/map?stop_id={self.stop_id}', name = "/api/stop/map")

if (
Expand Down Expand Up @@ -126,7 +166,7 @@ def stop_details(self):
@task(5)
def trip_details(self):
if self.stop_id is None:
self.stop_id = random.choice(all_stop_ids)
self.stop_id = random.choice(all_stations_and_bus)
predictions_for_stop = requests.get(
"https://api-v3.mbta.com/predictions",
params={"stop": self.stop_id}, headers=self.v3_api_headers).json()["data"]
Expand Down
2 changes: 1 addition & 1 deletion mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"polyline": {:hex, :polyline, "1.4.0", "36666a3d010692d91d89501e13d385b6b136ef446f05814fb2e90149349d5a14", [:mix], [{:vector, "~> 1.0", [hex: :vector, repo: "hexpm", optional: false]}], "hexpm", "0e1e57497ba05f0355e23d722b03d5dc9a68d5d0c17c9f2dd5efefaa96f8960d"},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
"req": {:hex, :req, "0.5.7", "b722680e03d531a2947282adff474362a48a02aa54b131196fbf7acaff5e4cee", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "c6035374615120a8923e8089d0c21a3496cf9eda2d287b806081b8f323ceee29"},
"sentry": {:hex, :sentry, "10.7.1", "33392222d80ccff99c503f972998d2858b4c1e5aca2219a34269b68dacba8e7d", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_ownership, "~> 0.3.0 or ~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "56291312397bf2b6afab6cf4f7aa1f27413b0eb2ceeb63b8aab2d7658aaea882"},
"sentry": {:hex, :sentry, "10.8.0", "1e8cc0ef21401e5914e6fc2f37489d6c685d31a0556dbd8ab4709cc1587a7232", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_ownership, "~> 0.3.0 or ~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "92549e7ba776b7ccfed4e74d58987272d37d99606b130e4141bc015a1a8e4235"},
"server_sent_event_stage": {:hex, :server_sent_event_stage, "1.2.1", "ede8c63496e19f039972503aa242cb4c16a301d495be7d9fdda2f952298cbf0c", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:ex_doc, "~> 0.22", [hex: :ex_doc, repo: "hexpm", optional: true]}, {:gen_stage, "~> 1.1", [hex: :gen_stage, repo: "hexpm", optional: false]}, {:mint, "~> 1.4", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "5b84b2c886bfa3ab38143d424eff6ec9d224e65ca576652aab762ed9d11847c3"},
"slipstream": {:hex, :slipstream, "1.1.1", "7e56f62f1a9ee81351e3c36f57b9b187e00dc2f470e70ba46ea7ad16e80b061f", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mint_web_socket, "~> 0.2 or ~> 1.0", [hex: :mint_web_socket, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.1 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c20e420cde1654329d38ec3aa1c0e4debbd4c91ca421491e7984ad4644e638a6"},
"sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"},
Expand Down

0 comments on commit 962f78b

Please sign in to comment.