Revert "Fix Blockstore XBlock Runtime's handling of occasional S3 errors"

This commit is contained in:
David Ormsbee
2020-03-12 15:09:23 -04:00
committed by GitHub
parent d15402db8d
commit 09c5432415
6 changed files with 25 additions and 50 deletions

View File

@@ -180,9 +180,7 @@ class BlockstoreFieldData(FieldData):
# Otherwise, this is an anomalous get() before the XML was fully loaded:
# This could happen if an XBlock's parse_xml() method tried to read a field before setting it,
# if an XBlock read field data in its constructor (forbidden), or if an XBlock was loaded via
# some means other than runtime.get_block(). One way this can happen is if you log/print an XBlock during
# XML parsing, because ScopedStorageMixin.__repr__ will try to print all field values, and any fields which
# aren't mentioned in the XML (which are left at their default) will be "not loaded yet."
# some means other than runtime.get_block()
log.exception(
"XBlock %s tried to read from field data (%s) that wasn't loaded from Blockstore!",
block.scope_ids.usage_id, name,

View File

@@ -13,7 +13,7 @@ from xblock.fields import ScopeIds
from openedx.core.djangoapps.xblock.learning_context.manager import get_learning_context_impl
from openedx.core.djangoapps.xblock.runtime.runtime import XBlockRuntime
from openedx.core.djangoapps.xblock.runtime.olx_parsing import parse_xblock_include, BundleFormatException
from openedx.core.djangoapps.xblock.runtime.olx_parsing import parse_xblock_include
from openedx.core.djangoapps.xblock.runtime.serializer import serialize_xblock
from openedx.core.djangolib.blockstore_cache import (
BundleCache,
@@ -85,12 +85,7 @@ class BlockstoreXBlockRuntime(XBlockRuntime):
This runtime API should normally be used via
runtime.get_block() -> block.parse_xml() -> runtime.add_node_as_child
"""
try:
parsed_include = parse_xblock_include(node)
except BundleFormatException:
# We need to log the XBlock ID or this will be hard to debug
log.error("BundleFormatException when parsing XBlock %s", block.scope_ids.usage_id)
raise # Also log details and stack trace
parsed_include = parse_xblock_include(node)
self.add_child_include(block, parsed_include)
def add_child_include(self, block, parsed_include):

View File

@@ -27,9 +27,6 @@ def parse_xblock_include(include_node):
# An XBlock include looks like:
# <xblock-include source="link_id" definition="block_type/definition_id" usage="alias" />
# Where "source" and "usage" are optional.
if include_node.tag != 'xblock-include':
# xss-lint: disable=python-wrap-html
raise BundleFormatException("Expected an <xblock-include /> XML node, but got <{}>".format(include_node.tag))
try:
definition_path = include_node.attrib['definition']
except KeyError:

View File

@@ -13,6 +13,7 @@ from datetime import datetime
from uuid import UUID
from django.core.cache import caches, InvalidCacheBackendError
from django.utils.lru_cache import lru_cache
from pytz import UTC
import requests
@@ -32,7 +33,7 @@ except InvalidCacheBackendError:
# (Note that we do usually explicitly invalidate this cache during write
# operations though, so this setting mostly affects actions by external systems
# on Blockstore or bugs where we left out the cache invalidation step.)
MAX_BLOCKSTORE_CACHE_DELAY = 60 * 5
MAX_BLOCKSTORE_CACHE_DELAY = 60
class BundleCache(object):
@@ -143,19 +144,18 @@ def get_bundle_version_number(bundle_uuid, draft_name=None):
return version
@lru_cache(maxsize=200)
def get_bundle_version_files_cached(bundle_uuid, bundle_version):
"""
Get the files in the specified BundleVersion. Since BundleVersions are
immutable, this should be cached as aggressively as possible.
immutable, this should be cached as aggressively as possible (ideally
it would be infinitely but we don't want to use up all available memory).
So this method uses lru_cache() to cache results in process-local memory.
(Note: This can't use BundleCache because BundleCache only associates data
with the most recent bundleversion, not a specified bundleversion)
"""
# Use the blockstore django cache directly; this can't use BundleCache because BundleCache only associates data
# with the most recent bundleversion, not a specified bundleversion
cache_key = 'bundle_version_files:{}:{}'.format(bundle_uuid, bundle_version)
result = cache.get(cache_key)
if result is None:
result = blockstore_api.get_bundle_version_files(bundle_uuid, bundle_version)
cache.set(cache_key, result, timeout=None) # Cache forever since bundle versions are immutable
return result
return blockstore_api.get_bundle_version_files(bundle_uuid, bundle_version)
def get_bundle_draft_files_cached(bundle_uuid, draft_name):
@@ -202,34 +202,24 @@ def get_bundle_file_data_with_cache(bundle_uuid, path, bundle_version=None, draf
cached list of files in each bundle if available.
"""
file_info = get_bundle_file_metadata_with_cache(bundle_uuid, path, bundle_version, draft_name)
response = requests.get(file_info.url)
if response.status_code != 200:
try:
error_response = response.content.decode('utf-8')[:500]
except UnicodeDecodeError:
error_response = '(error details unavailable - response was not a [unicode] string)'
raise blockstore_api.BundleStorageError(
"Unexpected error trying to read {} from bundle {}: \n{}".format(path, bundle_uuid, error_response)
)
return response.content
with requests.get(file_info.url, stream=True) as r:
return r.content
@lru_cache(maxsize=200)
def get_bundle_version_direct_links_cached(bundle_uuid, bundle_version):
"""
Get the direct links in the specified BundleVersion. Since BundleVersions
are immutable, this should be cached as aggressively as possible.
are immutable, this should be cached as aggressively as possible (ideally
it would be infinitely but we don't want to use up all available memory).
So this method uses lru_cache() to cache results in process-local memory.
(Note: This can't use BundleCache because BundleCache only associates data
with the most recent bundleversion, not a specified bundleversion)
"""
# Use the blockstore django cache directly; this can't use BundleCache because BundleCache only associates data
# with the most recent bundleversion, not a specified bundleversion
cache_key = 'bundle_version_direct_links:{}:{}'.format(bundle_uuid, bundle_version)
result = cache.get(cache_key)
if result is None:
result = {
link.name: link.direct
for link in blockstore_api.get_bundle_version_links(bundle_uuid, bundle_version).values()
}
cache.set(cache_key, result, timeout=None) # Cache forever since bundle versions are immutable
return result
return {
link.name: link.direct for link in blockstore_api.get_bundle_version_links(bundle_uuid, bundle_version).values()
}
def get_bundle_draft_direct_links_cached(bundle_uuid, draft_name):

View File

@@ -51,5 +51,4 @@ from .exceptions import (
BundleNotFound,
DraftNotFound,
BundleFileNotFound,
BundleStorageError,
)

View File

@@ -25,7 +25,3 @@ class DraftNotFound(NotFound):
class BundleFileNotFound(NotFound):
pass
class BundleStorageError(BlockstoreException):
pass