Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
96b1a17b
Commit
96b1a17b
authored
Nov 10, 2014
by
Usman Khalid
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5816 from edx/usman/plat71-mongo-autoreconnect-errors-2
Proxy to retry on mongo Autoreconnect errors.
parents
6df676b9
5fa11047
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
54 additions
and
65 deletions
+54
-65
common/lib/xmodule/xmodule/modulestore/mongo/base.py
+33
-22
common/lib/xmodule/xmodule/modulestore/split_mongo/mongo_connection.py
+13
-39
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
+3
-0
common/lib/xmodule/xmodule/modulestore/tests/test_split_w_old_mongo.py
+4
-4
requirements/edx/github.txt
+1
-0
No files found.
common/lib/xmodule/xmodule/modulestore/mongo/base.py
View file @
96b1a17b
...
@@ -20,34 +20,37 @@ import re
...
@@ -20,34 +20,37 @@ import re
from
uuid
import
uuid4
from
uuid
import
uuid4
from
bson.son
import
SON
from
bson.son
import
SON
from
contracts
import
contract
,
new_contract
from
datetime
import
datetime
from
fs.osfs
import
OSFS
from
fs.osfs
import
OSFS
from
mongodb_proxy
import
MongoProxy
,
autoretry_read
from
path
import
path
from
path
import
path
from
datetime
import
datetime
from
pytz
import
UTC
from
pytz
import
UTC
from
contracts
import
contract
,
new_contract
from
contracts
import
contract
,
new_contract
from
operator
import
itemgetter
from
operator
import
itemgetter
from
sortedcontainers
import
SortedListWithKey
from
sortedcontainers
import
SortedListWithKey
from
importlib
import
import_module
from
importlib
import
import_module
from
xmodule.errortracker
import
null_error_tracker
,
exc_info_to_str
from
opaque_keys.edx.keys
import
UsageKey
,
CourseKey
,
AssetKey
from
xmodule.mako_module
import
MakoDescriptorSystem
from
opaque_keys.edx.locations
import
Location
from
xmodule.error_module
import
ErrorDescriptor
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
from
xblock.runtime
import
KvsFieldData
from
opaque_keys.edx.locator
import
CourseLocator
from
xblock.core
import
XBlock
from
xblock.exceptions
import
InvalidScopeError
from
xblock.exceptions
import
InvalidScopeError
from
xblock.fields
import
Scope
,
ScopeIds
,
Reference
,
ReferenceList
,
ReferenceValueDict
from
xblock.fields
import
Scope
,
ScopeIds
,
Reference
,
ReferenceList
,
ReferenceValueDict
from
xblock.runtime
import
KvsFieldData
from
xmodule.assetstore
import
AssetMetadata
from
xmodule.error_module
import
ErrorDescriptor
from
xmodule.errortracker
import
null_error_tracker
,
exc_info_to_str
from
xmodule.exceptions
import
HeartbeatFailure
from
xmodule.mako_module
import
MakoDescriptorSystem
from
xmodule.modulestore
import
ModuleStoreWriteBase
,
ModuleStoreEnum
,
BulkOperationsMixin
,
BulkOpsRecord
from
xmodule.modulestore
import
ModuleStoreWriteBase
,
ModuleStoreEnum
,
BulkOperationsMixin
,
BulkOpsRecord
from
xmodule.modulestore.draft_and_published
import
ModuleStoreDraftAndPublished
,
DIRECT_ONLY_CATEGORIES
from
xmodule.modulestore.draft_and_published
import
ModuleStoreDraftAndPublished
,
DIRECT_ONLY_CATEGORIES
from
opaque_keys.edx.locations
import
Locatio
n
from
xmodule.modulestore.edit_info
import
EditInfoRuntimeMixi
n
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
,
DuplicateCourseError
,
ReferentialIntegrityError
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
,
DuplicateCourseError
,
ReferentialIntegrityError
from
xmodule.modulestore.inheritance
import
InheritanceMixin
,
inherit_metadata
,
InheritanceKeyValueStore
from
xmodule.modulestore.inheritance
import
InheritanceMixin
,
inherit_metadata
,
InheritanceKeyValueStore
from
xblock.core
import
XBlock
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
from
opaque_keys.edx.locator
import
CourseLocator
from
opaque_keys.edx.keys
import
UsageKey
,
CourseKey
,
AssetKey
from
xmodule.exceptions
import
HeartbeatFailure
from
xmodule.modulestore.edit_info
import
EditInfoRuntimeMixin
from
xmodule.assetstore
import
AssetMetadata
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -442,6 +445,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
...
@@ -442,6 +445,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
error_tracker
=
null_error_tracker
,
error_tracker
=
null_error_tracker
,
i18n_service
=
None
,
i18n_service
=
None
,
fs_service
=
None
,
fs_service
=
None
,
retry_wait_time
=
0.1
,
**
kwargs
):
**
kwargs
):
"""
"""
:param doc_store_config: must have a host, db, and collection entries. Other common entries: port, tz_aware.
:param doc_store_config: must have a host, db, and collection entries. Other common entries: port, tz_aware.
...
@@ -455,15 +459,18 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
...
@@ -455,15 +459,18 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
"""
"""
Create & open the connection, authenticate, and provide pointers to the collection
Create & open the connection, authenticate, and provide pointers to the collection
"""
"""
self
.
database
=
pymongo
.
database
.
Database
(
self
.
database
=
MongoProxy
(
pymongo
.
MongoClient
(
pymongo
.
database
.
Database
(
host
=
host
,
pymongo
.
MongoClient
(
port
=
port
,
host
=
host
,
tz_aware
=
tz_aware
,
port
=
port
,
document_class
=
dict
,
tz_aware
=
tz_aware
,
**
kwargs
document_class
=
dict
,
**
kwargs
),
db
),
),
db
wait_time
=
retry_wait_time
)
)
self
.
collection
=
self
.
database
[
collection
]
self
.
collection
=
self
.
database
[
collection
]
...
@@ -516,9 +523,10 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
...
@@ -516,9 +523,10 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
super
(
MongoModuleStore
,
self
)
.
_drop_database
()
super
(
MongoModuleStore
,
self
)
.
_drop_database
()
connection
=
self
.
collection
.
database
.
connection
connection
=
self
.
collection
.
database
.
connection
connection
.
drop_database
(
self
.
collection
.
database
)
connection
.
drop_database
(
self
.
collection
.
database
.
proxied_object
)
connection
.
close
()
connection
.
close
()
@autoretry_read
()
def
fill_in_run
(
self
,
course_key
):
def
fill_in_run
(
self
,
course_key
):
"""
"""
In mongo some course_keys are used without runs. This helper function returns
In mongo some course_keys are used without runs. This helper function returns
...
@@ -692,6 +700,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
...
@@ -692,6 +700,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
item
[
'location'
]
=
item
[
'_id'
]
item
[
'location'
]
=
item
[
'_id'
]
del
item
[
'_id'
]
del
item
[
'_id'
]
@autoretry_read
()
def
_query_children_for_cache_children
(
self
,
course_key
,
items
):
def
_query_children_for_cache_children
(
self
,
course_key
,
items
):
"""
"""
Generate a pymongo in query for finding the items and return the payloads
Generate a pymongo in query for finding the items and return the payloads
...
@@ -796,6 +805,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
...
@@ -796,6 +805,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
for
item
in
items
for
item
in
items
]
]
@autoretry_read
()
def
get_courses
(
self
,
**
kwargs
):
def
get_courses
(
self
,
**
kwargs
):
'''
'''
Returns a list of course descriptors.
Returns a list of course descriptors.
...
@@ -927,6 +937,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
...
@@ -927,6 +937,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
for
key
in
(
'tag'
,
'org'
,
'course'
,
'category'
,
'name'
,
'revision'
)
for
key
in
(
'tag'
,
'org'
,
'course'
,
'category'
,
'name'
,
'revision'
)
])
])
@autoretry_read
()
def
get_items
(
def
get_items
(
self
,
self
,
course_id
,
course_id
,
...
...
common/lib/xmodule/xmodule/modulestore/split_mongo/mongo_connection.py
View file @
96b1a17b
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
Segregation of pymongo functions from the data modeling mechanisms for split modulestore.
Segregation of pymongo functions from the data modeling mechanisms for split modulestore.
"""
"""
import
re
import
re
from
mongodb_proxy
import
autoretry_read
,
MongoProxy
import
pymongo
import
pymongo
import
time
import
time
...
@@ -68,50 +69,28 @@ def structure_to_mongo(structure):
...
@@ -68,50 +69,28 @@ def structure_to_mongo(structure):
return
new_structure
return
new_structure
def
autoretry_read
(
wait
=
0.1
,
retries
=
5
):
"""
Automatically retry a read-only method in the case of a pymongo
AutoReconnect exception.
See http://emptysqua.re/blog/save-the-monkey-reliably-writing-to-mongodb/
for a discussion of this technique.
"""
def
decorate
(
fn
):
@wraps
(
fn
)
def
wrapper
(
*
args
,
**
kwargs
):
for
attempt
in
xrange
(
retries
):
try
:
return
fn
(
*
args
,
**
kwargs
)
break
except
AutoReconnect
:
# Reraise if we failed on our last attempt
if
attempt
==
retries
-
1
:
raise
if
wait
:
time
.
sleep
(
wait
)
return
wrapper
return
decorate
class
MongoConnection
(
object
):
class
MongoConnection
(
object
):
"""
"""
Segregation of pymongo functions from the data modeling mechanisms for split modulestore.
Segregation of pymongo functions from the data modeling mechanisms for split modulestore.
"""
"""
def
__init__
(
def
__init__
(
self
,
db
,
collection
,
host
,
port
=
27017
,
tz_aware
=
True
,
user
=
None
,
password
=
None
,
asset_collection
=
None
,
**
kwargs
self
,
db
,
collection
,
host
,
port
=
27017
,
tz_aware
=
True
,
user
=
None
,
password
=
None
,
asset_collection
=
None
,
retry_wait_time
=
0.1
,
**
kwargs
):
):
"""
"""
Create & open the connection, authenticate, and provide pointers to the collections
Create & open the connection, authenticate, and provide pointers to the collections
"""
"""
self
.
database
=
pymongo
.
database
.
Database
(
self
.
database
=
MongoProxy
(
pymongo
.
MongoClient
(
pymongo
.
database
.
Database
(
host
=
host
,
pymongo
.
MongoClient
(
port
=
port
,
host
=
host
,
tz_aware
=
tz_aware
,
port
=
port
,
**
kwargs
tz_aware
=
tz_aware
,
**
kwargs
),
db
),
),
db
wait_time
=
retry_wait_time
)
)
# Remove when adding official Split support for asset metadata storage.
# Remove when adding official Split support for asset metadata storage.
...
@@ -142,7 +121,6 @@ class MongoConnection(object):
...
@@ -142,7 +121,6 @@ class MongoConnection(object):
else
:
else
:
raise
HeartbeatFailure
(
"Can't connect to {}"
.
format
(
self
.
database
.
name
))
raise
HeartbeatFailure
(
"Can't connect to {}"
.
format
(
self
.
database
.
name
))
@autoretry_read
()
def
get_structure
(
self
,
key
):
def
get_structure
(
self
,
key
):
"""
"""
Get the structure from the persistence mechanism whose id is the given key
Get the structure from the persistence mechanism whose id is the given key
...
@@ -195,7 +173,6 @@ class MongoConnection(object):
...
@@ -195,7 +173,6 @@ class MongoConnection(object):
"""
"""
self
.
structures
.
insert
(
structure_to_mongo
(
structure
))
self
.
structures
.
insert
(
structure_to_mongo
(
structure
))
@autoretry_read
()
def
get_course_index
(
self
,
key
,
ignore_case
=
False
):
def
get_course_index
(
self
,
key
,
ignore_case
=
False
):
"""
"""
Get the course_index from the persistence mechanism whose id is the given key
Get the course_index from the persistence mechanism whose id is the given key
...
@@ -212,7 +189,6 @@ class MongoConnection(object):
...
@@ -212,7 +189,6 @@ class MongoConnection(object):
}
}
return
self
.
course_index
.
find_one
(
query
)
return
self
.
course_index
.
find_one
(
query
)
@autoretry_read
()
def
find_matching_course_indexes
(
self
,
branch
=
None
,
search_targets
=
None
):
def
find_matching_course_indexes
(
self
,
branch
=
None
,
search_targets
=
None
):
"""
"""
Find the course_index matching particular conditions.
Find the course_index matching particular conditions.
...
@@ -271,14 +247,12 @@ class MongoConnection(object):
...
@@ -271,14 +247,12 @@ class MongoConnection(object):
'run'
:
course_index
[
'run'
],
'run'
:
course_index
[
'run'
],
})
})
@autoretry_read
()
def
get_definition
(
self
,
key
):
def
get_definition
(
self
,
key
):
"""
"""
Get the definition from the persistence mechanism whose id is the given key
Get the definition from the persistence mechanism whose id is the given key
"""
"""
return
self
.
definitions
.
find_one
({
'_id'
:
key
})
return
self
.
definitions
.
find_one
({
'_id'
:
key
})
@autoretry_read
()
def
get_definitions
(
self
,
definitions
):
def
get_definitions
(
self
,
definitions
):
"""
"""
Retrieve all definitions listed in `definitions`.
Retrieve all definitions listed in `definitions`.
...
...
common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
View file @
96b1a17b
...
@@ -56,6 +56,7 @@ import datetime
...
@@ -56,6 +56,7 @@ import datetime
import
logging
import
logging
from
contracts
import
contract
,
new_contract
from
contracts
import
contract
,
new_contract
from
importlib
import
import_module
from
importlib
import
import_module
from
mongodb_proxy
import
autoretry_read
from
path
import
path
from
path
import
path
from
pytz
import
UTC
from
pytz
import
UTC
from
bson.objectid
import
ObjectId
from
bson.objectid
import
ObjectId
...
@@ -775,6 +776,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
...
@@ -775,6 +776,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
# add it in the envelope for the structure.
# add it in the envelope for the structure.
return
CourseEnvelope
(
course_key
.
replace
(
version_guid
=
version_guid
),
entry
)
return
CourseEnvelope
(
course_key
.
replace
(
version_guid
=
version_guid
),
entry
)
@autoretry_read
()
def
get_courses
(
self
,
branch
,
**
kwargs
):
def
get_courses
(
self
,
branch
,
**
kwargs
):
'''
'''
Returns a list of course descriptors matching any given qualifiers.
Returns a list of course descriptors matching any given qualifiers.
...
@@ -2631,6 +2633,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
...
@@ -2631,6 +2633,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
"""
"""
structure
[
'blocks'
][
block_key
]
=
content
structure
[
'blocks'
][
block_key
]
=
content
@autoretry_read
()
def
find_courses_by_search_target
(
self
,
field_name
,
field_value
):
def
find_courses_by_search_target
(
self
,
field_name
,
field_value
):
"""
"""
Find all the courses which cached that they have the given field with the given value.
Find all the courses which cached that they have the given field with the given value.
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_split_w_old_mongo.py
View file @
96b1a17b
...
@@ -70,9 +70,9 @@ class SplitWMongoCourseBoostrapper(unittest.TestCase):
...
@@ -70,9 +70,9 @@ class SplitWMongoCourseBoostrapper(unittest.TestCase):
Remove the test collections, close the db connection
Remove the test collections, close the db connection
"""
"""
split_db
=
self
.
split_mongo
.
db
split_db
=
self
.
split_mongo
.
db
split_db
.
drop_collection
(
split_db
.
course_index
)
split_db
.
drop_collection
(
split_db
.
course_index
.
proxied_object
)
split_db
.
drop_collection
(
split_db
.
structures
)
split_db
.
drop_collection
(
split_db
.
structures
.
proxied_object
)
split_db
.
drop_collection
(
split_db
.
definitions
)
split_db
.
drop_collection
(
split_db
.
definitions
.
proxied_object
)
def
tear_down_mongo
(
self
):
def
tear_down_mongo
(
self
):
"""
"""
...
@@ -80,7 +80,7 @@ class SplitWMongoCourseBoostrapper(unittest.TestCase):
...
@@ -80,7 +80,7 @@ class SplitWMongoCourseBoostrapper(unittest.TestCase):
"""
"""
split_db
=
self
.
split_mongo
.
db
split_db
=
self
.
split_mongo
.
db
# old_mongo doesn't give a db attr, but all of the dbs are the same
# old_mongo doesn't give a db attr, but all of the dbs are the same
split_db
.
drop_collection
(
self
.
draft_mongo
.
collection
)
split_db
.
drop_collection
(
self
.
draft_mongo
.
collection
.
proxied_object
)
def
_create_item
(
self
,
category
,
name
,
data
,
metadata
,
parent_category
,
parent_name
,
draft
=
True
,
split
=
True
):
def
_create_item
(
self
,
category
,
name
,
data
,
metadata
,
parent_category
,
parent_name
,
draft
=
True
,
split
=
True
):
"""
"""
...
...
requirements/edx/github.txt
View file @
96b1a17b
...
@@ -11,6 +11,7 @@
...
@@ -11,6 +11,7 @@
-e git+https://github.com/edx/django-pipeline.git@88ec8a011e481918fdc9d2682d4017c835acd8be#egg=django-pipeline
-e git+https://github.com/edx/django-pipeline.git@88ec8a011e481918fdc9d2682d4017c835acd8be#egg=django-pipeline
-e git+https://github.com/edx/django-wiki.git@cd0b2b31997afccde519fe5b3365e61a9edb143f#egg=django-wiki
-e git+https://github.com/edx/django-wiki.git@cd0b2b31997afccde519fe5b3365e61a9edb143f#egg=django-wiki
-e git+https://github.com/edx/django-oauth2-provider.git@0.2.7-fork-edx-2#egg=django-oauth2-provider
-e git+https://github.com/edx/django-oauth2-provider.git@0.2.7-fork-edx-2#egg=django-oauth2-provider
-e git+https://github.com/edx/MongoDBProxy.git@efe14679c9263ab491916ed960f5930127e05faf#egg=mongodb_proxy
-e git+https://github.com/gabrielfalcao/lettuce.git@cccc3978ad2df82a78b6f9648fe2e9baddd22f88#egg=lettuce
-e git+https://github.com/gabrielfalcao/lettuce.git@cccc3978ad2df82a78b6f9648fe2e9baddd22f88#egg=lettuce
-e git+https://github.com/dementrock/pystache_custom.git@776973740bdaad83a3b029f96e415a7d1e8bec2f#egg=pystache_custom-dev
-e git+https://github.com/dementrock/pystache_custom.git@776973740bdaad83a3b029f96e415a7d1e8bec2f#egg=pystache_custom-dev
-e git+https://github.com/eventbrite/zendesk.git@d53fe0e81b623f084e91776bcf6369f8b7b63879#egg=zendesk
-e git+https://github.com/eventbrite/zendesk.git@d53fe0e81b623f084e91776bcf6369f8b7b63879#egg=zendesk
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment