Work on updating eve_proxy for Django 1.4 and TZ support.

This commit is contained in:
2012-05-20 11:31:56 +01:00
parent c03989bd00
commit e1dc20ff2e
5 changed files with 45 additions and 41 deletions

View File

@@ -1,4 +1,4 @@
VERSION = (0, 4) VERSION = (0, 5)
# Dynamically calculate the version based on VERSION tuple # Dynamically calculate the version based on VERSION tuple
if len(VERSION)>2 and VERSION[2] is not None: if len(VERSION)>2 and VERSION[2] is not None:

View File

@@ -8,6 +8,7 @@ from xml.dom import minidom
from django.db import models, IntegrityError from django.db import models, IntegrityError
from django.conf import settings from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from django.utils.timezone import utc, now
from eve_proxy.exceptions import * from eve_proxy.exceptions import *
@@ -77,7 +78,7 @@ class CachedDocumentManager(models.Manager):
doc = CachedDocument(pk=doc_key, url_path=url) doc = CachedDocument(pk=doc_key, url_path=url)
created = True created = True
if created or not doc.cached_until or datetime.utcnow() > doc.cached_until or no_cache: if created or not doc.cached_until or now() > doc.cached_until or no_cache:
stat_update_count('eve_proxy_api_requests') stat_update_count('eve_proxy_api_requests')
req = urllib2.Request(url) req = urllib2.Request(url)
@@ -104,23 +105,29 @@ class CachedDocumentManager(models.Manager):
raise DocumentRetrievalError(e.reason) raise DocumentRetrievalError(e.reason)
else: else:
doc.body = unicode(conn.read(), 'utf-8') doc.body = unicode(conn.read(), 'utf-8')
doc.time_retrieved = datetime.utcnow() doc.time_retrieved = now()
error = 0 error = 0
try: try:
# Parse the response via minidom # Parse the response via minidom
dom = minidom.parseString(doc.body.encode('utf-8')) dom = minidom.parseString(doc.body.encode('utf-8'))
except: except:
doc.cached_until = datetime.utcnow() doc.cached_until = now()
else: else:
date = datetime.strptime(dom.getElementsByTagName('cachedUntil')[0].childNodes[0].nodeValue, '%Y-%m-%d %H:%M:%S')
# Add 30 seconds to the cache timers, avoid hitting too early and account for some minor clock skew. # Calculate the cache timer on the basis of the currentTime and cachedUntil fields provided by the API
doc.cached_until = date + timedelta(seconds=getattr(settings, 'EVE_PROXY_GLOBAL_CACHE_ADJUSTMENT', 30)) # This allows for clock skew not to fuck with the timers.
currenttime = datetime.strptime(dom.getElementsByTagName('currentTime')[0].childNodes[0].nodeValue, '%Y-%m-%d %H:%M:%S')
cacheuntil = datetime.strptime(dom.getElementsByTagName('cachedUntil')[0].childNodes[0].nodeValue, '%Y-%m-%d %H:%M:%S')
date = now() + (cacheuntil - currenttime)
# Add the global adjustment, to avoid CCP's hardline cache timers
doc.cached_until += timedelta(seconds=getattr(settings, 'EVE_PROXY_GLOBAL_CACHE_ADJUSTMENT', 30))
# Allow for tuning of individual pages with bad cache returns # Allow for tuning of individual pages with bad cache returns
adjustconfig = getattr(settings, 'EVE_PROXY_CACHE_ADJUSTMENTS', {}) adjustconfig = getattr(settings, 'EVE_PROXY_CACHE_ADJUSTMENTS', {})
if url_path.lower() in adjustconfig: if url_path.lower() in adjustconfig:
doc.cached_until = date + timedelta(seconds=adjustconfig[url_path.lower()]) doc.cached_until += timedelta(seconds=adjustconfig[url_path.lower()])
enode = dom.getElementsByTagName('error') enode = dom.getElementsByTagName('error')
if enode: if enode:

View File

@@ -4,6 +4,7 @@ from datetime import datetime
import time import time
from django.utils import unittest from django.utils import unittest
from django.utils.timezone import now
from eve_proxy.models import CachedDocument from eve_proxy.models import CachedDocument
from eve_proxy.exceptions import * from eve_proxy.exceptions import *
@@ -40,8 +41,8 @@ class CachedDocumentTestCase(unittest.TestCase):
""" Tests if objects are being cached correctly """ """ Tests if objects are being cached correctly """
url = '/server/ServerStatus.xml.aspx' url = '/server/ServerStatus.xml.aspx'
obj = CachedDocument.objects.api_query(url, no_cache=True) obj = CachedDocument.objects.api_query(url, no_cache=True)
obj2 = CachedDocument.objects.api_query(url) obj2 = CachedDocument.objects.api_query(url)
self.assertEqual(obj.pk, obj2.pk, "Objects are not caching correctly") self.assertEqual(obj.pk, obj2.pk, "Objects are not caching correctly")
@@ -51,7 +52,7 @@ class CachedDocumentTestCase(unittest.TestCase):
url = '/server/ServerStatus.xml.aspx' url = '/server/ServerStatus.xml.aspx'
obj = CachedDocument.objects.api_query(url, no_cache=True) obj = CachedDocument.objects.api_query(url, no_cache=True)
ret_time = obj.time_retrieved ret_time = obj.time_retrieved
obj.cached_until = datetime.utcnow() obj.cached_until = now()
obj.save() obj.save()
time.sleep(1) time.sleep(1)

View File

@@ -1,8 +1,10 @@
from django.conf.urls.defaults import * from django.conf.urls.defaults import *
from eve_proxy.views import EVEAPIProxyView
urlpatterns = patterns('eve_proxy.views', urlpatterns = patterns('eve_proxy.views',
# This view can be used just like EVE API's http://api.eve-online.com. # This view can be used just like EVE API's http://api.eve-online.com.
# Any parameters or URL paths are sent through the cache system and # Any parameters or URL paths are sent through the cache system and
# forwarded to the EVE API site as needed. # forwarded to the EVE API site as needed.
url(r'^', 'retrieve_xml', name='eve_proxy-retrieve_xml'), url(r'^', EVEAPIProxyView.as_view(), name='eveproxy-apiproxy'),
) )

View File

@@ -2,38 +2,32 @@ from django.core.urlresolvers import reverse
from django.http import HttpResponse, HttpResponseNotFound, HttpResponseServerError from django.http import HttpResponse, HttpResponseNotFound, HttpResponseServerError
from eve_proxy.models import CachedDocument from eve_proxy.models import CachedDocument
def retrieve_xml(request):
"""
A view that forwards EVE API requests through the cache system, either
retrieving a cached document or querying and caching as needed.
"""
# This is the URL path (minus the parameters).
url_path = request.META['PATH_INFO'].replace(reverse('eve_proxy.views.retrieve_xml'),"/")
# The parameters attached to the end of the URL path.
if request.method == 'POST': class EVEAPIProxyView(View):
p = request.POST """Allows for standard EVE API calls to be proxied through your application"""
else:
p = request.GET
# Convert the QuerySet object into a dict def get(self, request, *args, **kwargs):
params = {} return self.get_document(request, request.GET)
for key,value in p.items():
params[key] = value
if url_path == '/' or url_path == '':
# If they don't provide any kind of query, shoot a quick error message.
return HttpResponseNotFound('No API query specified.')
if 'userID' in params and not 'service' in params: def post(self, request, *args, **kwargs):
return HttpResponse('No Service ID provided.') return self.get_document(request, request.POST)
def get_document(self, request, params):
url_path = request.META['PATH_INFO'].replace(reverse('eveproxy-apiproxy'),"/")
try: if url_path == '/' or url_path == '':
cached_doc = CachedDocument.objects.api_query(url_path, params, exceptions=False) # If they don't provide any kind of query, shoot a quick error message.
except: return HttpResponseNotFound('No API query specified.')
return HttpResponseServerError('Error occured')
if 'userID' in params and not 'service' in params:
return HttpResponse('No Service ID provided.')
if cached_doc: try:
return HttpResponse(cached_doc.body, mimetype='text/xml') cached_doc = CachedDocument.objects.api_query(url_path, params, exceptions=False)
except:
return HttpResponseServerError('Error occured')
return HttpResponseNotFound('Error retrieving the document') if cached_doc:
return HttpResponse(cached_doc.body, mimetype='text/xml')
return HttpResponseNotFound('Error retrieving the document')