juftin / camply

camply, the campsite finder ⛺️ - a tool to find campsites at sold out campgrounds through sites like recreation.gov
https://juftin.com/camply/
MIT License
485 stars 94 forks source link

ReadTimeout: HTTPSConnectionPool(host='camping.bcparks.ca', port=443): Read timed out. (read timeout=30) #354

Open KyleSanderson opened 3 months ago

KyleSanderson commented 3 months ago
 /usr/local/lib/python3.11/site-packages/camply/providers/going_to_camp/going_to_camp_provider.py │
│ :522 in list_site_availability                                                                   │
│                                                                                                  │
│   519 │   │   if equipment_type_id:                                                              │
│   520 │   │   │   search_filter["subEquipmentCategoryId"] = equipment_type_id                    │
│   521 │   │                                                                                      │
│ ❱ 522 │   │   resources, additional_resources = self._find_matching_resources(                   │
│   523 │   │   │   campground.recreation_area_id, search_filter                                   │
│   524 │   │   )                                                                                  │
│   525                                                                                            │
│                                                                                                  │
│ /usr/local/lib/python3.11/site-packages/camply/providers/going_to_camp/going_to_camp_provider.py │
│ :448 in _find_matching_resources                                                                 │
│                                                                                                  │
│   445 │   │   return facility, campground_facility                                               │
│   446 │                                                                                          │
│   447 │   def _find_matching_resources(self, rec_area_id: int, search_filter: Dict[str, any]):   │
│ ❱ 448 │   │   results = self._api_request(rec_area_id, "MAPDATA", search_filter)                 │
│   449 │   │   availability_details = {                                                           │
│   450 │   │   │   search_filter["mapId"]: results["resourceAvailabilities"]                      │
│   451 │   │   }                                                                                  │
│                                                                                                  │
│ /usr/local/lib/python3.11/site-packages/camply/providers/going_to_camp/going_to_camp_provider.py │
│ :341 in _api_request                                                                             │
│                                                                                                  │
│   338 │   │   │   "User-Agent": UserAgent(browsers=["chrome"]).random,                           │
│   339 │   │   │   "Accept-Language": "en-US,en;q=0.9",                                           │
│   340 │   │   }                                                                                  │
│ ❱ 341 │   │   response = self.session.get(url=url, headers=headers, params=params, timeout=30)   │
│   342 │   │   if response.ok is False:                                                           │
│   343 │   │   │   error_message = f"Receiving bad data from GoingToCamp API: status_code: {res   │
│   344 │   │   │   logger.error(error_message)                                                    │
│                                                                                                  │
│ /usr/local/lib/python3.11/site-packages/requests/sessions.py:602 in get                          │
│                                                                                                  │
│   599 │   │   """                                                                                │
│   600 │   │                                                                                      │
│   601 │   │   kwargs.setdefault("allow_redirects", True)                                         │
│ ❱ 602 │   │   return self.request("GET", url, **kwargs)                                          │
│   603 │                                                                                          │
│   604 │   def options(self, url, **kwargs):                                                      │
│   605 │   │   r"""Sends a OPTIONS request. Returns :class:`Response` object.                     │
│                                                                                                  │
│ /usr/local/lib/python3.11/site-packages/requests/sessions.py:589 in request                      │
│                                                                                                  │
│   586 │   │   │   "allow_redirects": allow_redirects,                                            │
│   587 │   │   }                                                                                  │
│   588 │   │   send_kwargs.update(settings)                                                       │
│ ❱ 589 │   │   resp = self.send(prep, **send_kwargs)                                              │
│   590 │   │                                                                                      │
│   591 │   │   return resp                                                                        │
│   592                                                                                            │
│                                                                                                  │
│ /usr/local/lib/python3.11/site-packages/requests/sessions.py:703 in send                         │
│                                                                                                  │
│   700 │   │   start = preferred_clock()                                                          │
│   701 │   │                                                                                      │
│   702 │   │   # Send the request                                                                 │
│ ❱ 703 │   │   r = adapter.send(request, **kwargs)                                                │
│   704 │   │                                                                                      │
│   705 │   │   # Total elapsed time of the request (approximately)                                │
│   706 │   │   elapsed = preferred_clock() - start                                                │
│                                                                                                  │
│ /usr/local/lib/python3.11/site-packages/requests/adapters.py:532 in send                         │
│                                                                                                  │
│   529 │   │   │   │   # This branch is for urllib3 versions earlier than v1.22                   │
│   530 │   │   │   │   raise SSLError(e, request=request)                                         │
│   531 │   │   │   elif isinstance(e, ReadTimeoutError):                                          │
│ ❱ 532 │   │   │   │   raise ReadTimeout(e, request=request)                                      │
│   533 │   │   │   elif isinstance(e, _InvalidHeader):                                            │
│   534 │   │   │   │   raise InvalidHeader(e, request=request)                                    │
│   535 │   │   │   else:                                                                          │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
ReadTimeout: HTTPSConnectionPool(host='camping.bcparks.ca', port=443): Read timed out. (read timeout=30)
Error: while running runtime: exit status 1
2024-07-26 18:22:43,024 [  CAMPLY]: camply, the campsite finder ⛺️
2024-07-26 18:22:43,044 [    INFO]: YAML File Parsed: camply.yml
2024-07-26 18:22:43,045 [    INFO]: Using Camply Provider: "GoingToCamp"
2024-07-26 18:22:43,054 [    INFO]: 12 booking nights selected for search, ranging from 2024-07-26 to 2024-08-31
2024-07-26 18:22:43,054 [    INFO]: Searching for booking nights on Friday and Saturday
2024-07-26 18:22:43,054 [    INFO]: 2 different months selected for search, ranging from 2024-07-26 to 2024-08-31
2024-07-26 18:22:43,078 [    INFO]: Searching for availabilities with 2 consecutive night stays.
2024-07-26 18:22:43,079 [    INFO]: Retrieving Facility Information for Recreation Area ID: `12`.
2024-07-26 18:22:57,008 [    INFO]: 11 Matching Campgrounds Found
2024-07-26 18:22:57,008 [    INFO]: ⛰  BC Parks (#12) - 🏕  Alice Lake Provincial Park (#-2147483647)
2024-07-26 18:22:57,009 [    INFO]: ⛰  BC Parks (#12) - 🏕  Birkenhead Lake Provincial Park (#-2147483640)
2024-07-26 18:22:57,009 [    INFO]: ⛰  BC Parks (#12) - 🏕  Cultus Lake Provincial Park (#-2147483623)
2024-07-26 18:22:57,009 [    INFO]: ⛰  BC Parks (#12) - 🏕  E. C. Manning Provincial Park (#-2147483618)
2024-07-26 18:22:57,009 [    INFO]: ⛰  BC Parks (#12) - 🏕  Golden Ears Provincial Park (#-2147483606)
2024-07-26 18:22:57,009 [    INFO]: ⛰  BC Parks (#12) - 🏕  Nairn Falls Provincial Park (#-2147483564)
2024-07-26 18:22:57,009 [    INFO]: ⛰  BC Parks (#12) - 🏕  Porpoise Bay Provincial Park (#-2147483551)
2024-07-26 18:22:57,009 [    INFO]: ⛰  BC Parks (#12) - 🏕  Porteau Cove Provincial Park (#-2147483550)
2024-07-26 18:22:57,009 [    INFO]: ⛰  BC Parks (#12) - 🏕  Rolley Lake Provincial Park (#-2147483543)
2024-07-26 18:22:57,009 [    INFO]: ⛰  BC Parks (#12) - 🏕  Sasquatch Provincial Park (#-2147483539)
2024-07-26 18:22:57,009 [    INFO]: ⛰  BC Parks (#12) - 🏕  Silver Lake Provincial Park (#-2147483535)
2024-07-26 18:22:57,010 [    INFO]: Searching for campsites every 5 minutes.
2024-07-26 18:22:57,010 [    INFO]: Notifications active via: <SilentNotifications>, <PushoverNotifications>
2024-07-26 18:23:02,247 [    INFO]: ❌ ❌ ❌ ❌ 0 Reservable Campsites Matching Search Preferences
2024-07-26 18:23:02,263 [    INFO]: No Campsites were found, we'll continue checking
juftin commented 3 months ago
#355 stacktrace

``` │ /usr/local/lib/python3.11/site-packages/camply/providers/going_to_camp/going_to_camp_provider.py │ │ :522 in list_site_availability │ │ │ │ 519 │ │ if equipment_type_id: │ │ 520 │ │ │ search_filter["subEquipmentCategoryId"] = equipment_type_id │ │ 521 │ │ │ │ ❱ 522 │ │ resources, additional_resources = self._find_matching_resources( │ │ 523 │ │ │ campground.recreation_area_id, search_filter │ │ 524 │ │ ) │ │ 525 │ │ │ │ /usr/local/lib/python3.11/site-packages/camply/providers/going_to_camp/going_to_camp_provider.py │ │ :448 in _find_matching_resources │ │ │ │ 445 │ │ return facility, campground_facility │ │ 446 │ │ │ 447 │ def _find_matching_resources(self, rec_area_id: int, search_filter: Dict[str, any]): │ │ ❱ 448 │ │ results = self._api_request(rec_area_id, "MAPDATA", search_filter) │ │ 449 │ │ availability_details = { │ │ 450 │ │ │ search_filter["mapId"]: results["resourceAvailabilities"] │ │ 451 │ │ } │ │ │ │ /usr/local/lib/python3.11/site-packages/camply/providers/going_to_camp/going_to_camp_provider.py │ │ :341 in _api_request │ │ │ │ 338 │ │ │ "User-Agent": UserAgent(browsers=["chrome"]).random, │ │ 339 │ │ │ "Accept-Language": "en-US,en;q=0.9", │ │ 340 │ │ } │ │ ❱ 341 │ │ response = self.session.get(url=url, headers=headers, params=params, timeout=30) │ │ 342 │ │ if response.ok is False: │ │ 343 │ │ │ error_message = f"Receiving bad data from GoingToCamp API: status_code: {res │ │ 344 │ │ │ logger.error(error_message) │ │ │ │ /usr/local/lib/python3.11/site-packages/requests/sessions.py:602 in get │ │ │ │ 599 │ │ """ │ │ 600 │ │ │ │ 601 │ │ kwargs.setdefault("allow_redirects", True) │ │ ❱ 602 │ │ return self.request("GET", url, **kwargs) │ │ 603 │ │ │ 604 │ def options(self, url, **kwargs): │ │ 605 │ │ r"""Sends a OPTIONS request. Returns :class:`Response` object. │ │ │ │ /usr/local/lib/python3.11/site-packages/requests/sessions.py:589 in request │ │ │ │ 586 │ │ │ "allow_redirects": allow_redirects, │ │ 587 │ │ } │ │ 588 │ │ send_kwargs.update(settings) │ │ ❱ 589 │ │ resp = self.send(prep, **send_kwargs) │ │ 590 │ │ │ │ 591 │ │ return resp │ │ 592 │ │ │ │ /usr/local/lib/python3.11/site-packages/requests/sessions.py:703 in send │ │ │ │ 700 │ │ start = preferred_clock() │ │ 701 │ │ │ │ 702 │ │ # Send the request │ │ ❱ 703 │ │ r = adapter.send(request, **kwargs) │ │ 704 │ │ │ │ 705 │ │ # Total elapsed time of the request (approximately) │ │ 706 │ │ elapsed = preferred_clock() - start │ │ │ │ /usr/local/lib/python3.11/site-packages/requests/adapters.py:519 in send │ │ │ │ 516 │ │ │ │ # This branch is for urllib3 v1.22 and later. │ │ 517 │ │ │ │ raise SSLError(e, request=request) │ │ 518 │ │ │ │ │ ❱ 519 │ │ │ raise ConnectionError(e, request=request) │ │ 520 │ │ │ │ 521 │ │ except ClosedPoolError as e: │ │ 522 │ │ │ raise ConnectionError(e, request=request) │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ ConnectionError: HTTPSConnectionPool(host='camping.bcparks.ca', port=443): Max retries exceeded with url: /api/availability/map?mapId=-2147483647&resourceLocationId=-2147483647&bookingCategoryId=0&startDate=2024-07-27&endDate=2024-09-02& isReserving=True&getDailyAvailability=False&partySize=1&numEquipment=1&equipmentCategoryId=-32768 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 101] Network is unreachable')) Error: while running runtime: exit status 1 ```

juftin commented 3 months ago

354 and #355 both seem to indicate that the camping.bcparks.ca API experienced downtime which led to the exceptions. Camply has some exception handling that should allow for some downtime, but if an API is down for long enough then an exception is expected. I will make sure that the GoingToCamp provider is using the same exception handling as other providers to allow for limited API downtime.

KyleSanderson commented 3 months ago

I'd just prefer it keeps hitting the endpoint, and after 10 failures or 20 or something use pushover to notify me its down, and notify me once it comes back after it hits the determined failure.

KyleSanderson commented 3 months ago
│   342 │   │   if response.ok is False:                                                           │
│   343 │   │   │   error_message = f"Receiving bad data from GoingToCamp API: status_code: {res   │
│   344 │   │   │   logger.error(error_message)                                                    │
│ ❱ 345 │   │   │   raise ConnectionError(error_message)                                           │
│   346 │   │                                                                                      │
│   347 │   │   return json.loads(response.content)                                                │
│   348                                                                                            │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
ConnectionError: Receiving bad data from GoingToCamp API: status_code: 403: <!DOCTYPE html>
<html>
<head>
    <title>Web App - Unavailable</title>
    <style type="text/css">
        html {
            height: 100%;
            width: 100%;
        }

        #feature {
            width: 960px;
            margin: 95px auto 0 auto;
            overflow: auto;
        }

        #content {
            font-family: "Segoe UI";
            font-weight: normal;
            font-size: 22px;
            color: #ffffff;
            float: left;
            width: 460px;
            margin-top: 68px;
            margin-left: 0px;
            vertical-align: middle;
        }

            #content h1 {
                font-family: "Segoe UI Light";
                color: #ffffff;
                font-weight: normal;
                font-size: 60px;
                line-height: 48pt;
                width: 800px;
            }

        p a, p a:visited, p a:active, p a:hover {
            color: #ffffff;
        }

        #content a.button {
            background: #0DBCF2;
            border: 1px solid #FFFFFF;
            color: #FFFFFF;
            display: inline-block;
            font-family: Segoe UI;
            font-size: 24px;
            line-height: 46px;
            margin-top: 10px;
            padding: 0 15px 3px;
            text-decoration: none;
        }

            #content a.button img {
                float: right;
                padding: 10px 0 0 15px;
            }

            #content a.button:hover {
                background: #1C75BC;
            }
    </style>
</head>
<body bgcolor="#00abec">
    <div id="feature">
            <div id="content">
                <h1 id="unavailable">Error 403 - This web app is stopped.</h1>
                <p id="tryAgain">The web app you have attempted to reach is currently stopped and does not accept any requests. Please try to reload the page or visit it again soon.</p>
                <p id="toAdmin">If you are the web app administrator, please find the common 403 error scenarios and resolution <a href="https://go.microsoft.com/fwlink/?linkid=2095007" target="_blank">here</a>. For further troubleshooting tools and
recommendations, please visit <a href="https://portal.azure.com/">Azure Portal</a>.</p>
        </div>
    </div>
</body>
</html>

Error: while running runtime: exit status 1

Man this is terrible right now. just going to run it in a loop in the shell I guess?