Repository: StackStorm/st2

Issue:
Support MongoDB 3.4
MongoDB 3.4 is the current latest stable release and we should eventually add support for it.

Sadly it won't be totally straight- forward, because that version includes some backward incompatible changes and we make sure it doesn't break stuff for existing users (for new installations it will probably be easier although there are still some pymongo changes we need to evaluate).


Discussion:
+1

Resolving patch:
diff --git a/st2common/st2common/models/db/__init__.py b/st2common/st2common/models/db/__init__.py
--- a/st2common/st2common/models/db/__init__.py
+++ b/st2common/st2common/models/db/__init__.py
@@ -15,6 +15,7 @@
 
 import copy
 import importlib
+import traceback
 import ssl as ssl_lib
 
 import six
@@ -114,7 +115,15 @@ def db_ensure_indexes():
 
         # Note: We need to ensure / create new indexes before removing extra ones
         LOG.debug('Ensuring indexes for model "%s"...' % (model_class.__name__))
-        model_class.ensure_indexes()
+
+        try:
+            model_class.ensure_indexes()
+        except Exception as e:
+            tb_msg = traceback.format_exc()
+            msg = 'Failed to ensure indexes for model "%s": %s' % (class_name, str(e))
+            msg += '\n\n' + tb_msg
+            exc_cls = type(e)
+            raise exc_cls(msg)
 
         if model_class.__name__ in INDEX_CLEANUP_MODEL_NAMES_BLACKLIST:
             LOG.debug('Skipping index cleanup for blacklisted model "%s"...' % (class_name))
diff --git a/st2common/st2common/models/db/stormbase.py b/st2common/st2common/models/db/stormbase.py
--- a/st2common/st2common/models/db/stormbase.py
+++ b/st2common/st2common/models/db/stormbase.py
@@ -121,9 +121,10 @@ class StormBaseDB(StormFoundationDB):
 
 class EscapedDictField(me.DictField):
 
-    def to_mongo(self, value):
+    def to_mongo(self, value, use_db_field=True, fields=None):
         value = mongoescape.escape_chars(value)
-        return super(EscapedDictField, self).to_mongo(value)
+        return super(EscapedDictField, self).to_mongo(value=value, use_db_field=use_db_field,
+                                                      fields=fields)
 
     def to_python(self, value):
         value = super(EscapedDictField, self).to_python(value)
@@ -139,9 +140,10 @@ def validate(self, value):
 
 class EscapedDynamicField(me.DynamicField):
 
-    def to_mongo(self, value):
+    def to_mongo(self, value, use_db_field=True, fields=None):
         value = mongoescape.escape_chars(value)
-        return super(EscapedDynamicField, self).to_mongo(value)
+        return super(EscapedDynamicField, self).to_mongo(value=value, use_db_field=use_db_field,
+                                                         fields=fields)
 
     def to_python(self, value):
         value = super(EscapedDynamicField, self).to_python(value)
@@ -201,8 +203,7 @@ def get_indexes(cls):
             {
                 'fields': ['uid'],
                 'unique': True,
-                'sparse': True,
-                'types': False
+                'sparse': True
             }
         ]
         return indexes
diff --git a/st2common/st2common/persistence/db_init.py b/st2common/st2common/persistence/db_init.py
--- a/st2common/st2common/persistence/db_init.py
+++ b/st2common/st2common/persistence/db_init.py
@@ -35,7 +35,7 @@ def _retry_if_connection_error(error):
     # Ideally, a special execption or atleast some exception code.
     # If this does become an issue look for "Cannot connect to database" at the
     # start of error msg.
-    is_connection_error = isinstance(error, mongoengine.connection.ConnectionError)
+    is_connection_error = isinstance(error, mongoengine.connection.MongoEngineConnectionError)
     if is_connection_error:
         LOG.warn('Retry on ConnectionError - %s', error)
     return is_connection_error


Test patch: