-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.py
85 lines (78 loc) · 2.91 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import webapp2
import logging
from models import BikeNetwork, BikeNetworkList
import json
import time
from google.appengine.ext.webapp import template
from google.appengine.ext import ndb
from google.appengine.api import urlfetch
from codec.codec import STALE_SYSTEM_SECONDS
from codec.gbfs import GbfsCodec
from codec.pybikes import PyBikesCodec
from models import SystemListElement, CompactElement
from http import RestHandler
from google.appengine.api import memcache
from caching import http_cached, http_purge, STATION_STATUS_TTL, STATION_INFO_TTL
CODECS = {
GbfsCodec.NAME: GbfsCodec(),
PyBikesCodec.NAME: PyBikesCodec()
}
class BikeNetworkStatusApi(RestHandler):
@http_cached(etag=True,ttl=STATION_STATUS_TTL)
def get(self,system_id):
system = BikeNetwork.get_by_id(system_id)
if not system:
self.response_error()
return
out = CODECS[system.codec].get_status(system)
self.json_response(out)
class BikeNetworkInfoApi(RestHandler):
@http_cached(etag=True,ttl=STATION_INFO_TTL)
def get(self,system_id):
system = BikeNetwork.get_by_id(system_id)
if not system:
self.response_error()
return
out = CODECS[system.codec].get_info(system)
self.json_response(out)
class BikeNetworkListApi(RestHandler):
@http_cached(etag=True,ttl=STATION_INFO_TTL)
def get(self):
out = BikeNetworkList.get_by_id("all")
if not out:
self.response_error()
return
self.json_response(out.networks)
class UpdateSystemsHandler(webapp2.RequestHandler):
def get(self):
entities = []
for codec_name, codec in CODECS.items():
logging.info("Refreshing %s..." % codec_name)
try:
codec_entities = codec.load()
for entity in codec_entities:
delta = time.time() - entity.last_updated
if entity.last_updated == 0 or delta < STALE_SYSTEM_SECONDS:
entities.append(entity)
else:
logging.info("Out of date '%s': %d seconds" % (entity.key.id(), delta))
except Exception as e:
logging.error("failed to load %s: %s", codec_name, e)
time.sleep(5)
ndb.delete_multi(
BikeNetwork.query().fetch(keys_only=True)
)
ndb.put_multi(entities)
out = []
for system in entities:
http_purge("/systems/%s/info" % system.key.id())
out.append(SystemListElement(system))
networks = BikeNetworkList(id="all",networks=CompactElement.of(out))
networks.put()
http_purge("/systems")
app = webapp2.WSGIApplication([
('/systems/([^/]+)/info', BikeNetworkInfoApi),
('/systems/([^/]+)/status', BikeNetworkStatusApi),
('/systems', BikeNetworkListApi),
('/load', UpdateSystemsHandler),
], debug=True)