Skip to content

Instantly share code, notes, and snippets.

@wys1203
Last active June 24, 2016 03:51
Show Gist options
  • Save wys1203/84e5efaac9f0219a00f404e6a8e746cd to your computer and use it in GitHub Desktop.
Save wys1203/84e5efaac9f0219a00f404e6a8e746cd to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function, absolute_import, division
from django.conf import settings
from multiprocessing import Lock
from pymongo import MongoClient
import six
__all__ = ["MongoDB"]
MONGO_DB = settings.MONGO_DB
class SingletonMetaclass(type):
def __new__(mcs, name, bases, attrs):
# Assume the target class is created (i.e. this method to be called) in the main thread.
cls = super(SingletonMetaclass, mcs).__new__(mcs, name, bases, attrs)
cls.__shared_instance_lock__ = Lock()
# cls.__shared_instances_pool__ = {}
return cls
def __call__(cls, db, collection):
with cls.__shared_instance_lock__:
# a = {}
# a.setdefault("a", []).append(1)
# a.setdefault("a", []).append(2)
# a["a"] == [1, 2]
# if collection not in cls.__shared_instances_pool__:
# cls.__shared_instances_pool__[collection] = super(SingletonMetaclass, cls).__call__(db, collection)
# return cls.__shared_instances_pool__[collection]
# return cls.__shared_instances_pool__.setdefault(collection, super(SingletonMetaclass, cls).__call__(db, collection))
try:
return cls.__shared_instance__
except AttributeError:
cls.__shared_instance__ = super(SingletonMetaclass, cls).__call__(db, collection)
return cls.__shared_instance__
# @six.add_metaclass(SingletonMetaclass)
class MongoDB(object):
""" Provides a RAII wrapper for PyMongo db connections.
Available collection functions limited to those in
attributes_to_pass. Number of simultaneous connection
users also tracked.
Example:
with MongoDB(db="iCHEF_db", collection="invoice") as m:
m.insert(...)
m.find(...)
m.update(... , upsert=True)
with MongoDB(db="iCHEF_db", collection="cancelled_invoice") as m:
m.insert(...)
m.find(...)
m.update(... , upsert=True)
"""
ATTRIBUTES_TO_PASS = ("update", "insert", "count", "find", "delete_one", "delete_many", "update_one", "update_many")
num_users = 0
_shared_mongo_client = None
_shared_mongo_client_lock = Lock()
# client = None
# num_users_lock = Lock()
def __init__(self, db, collection):
self._db_name = db
self._collection_name = collection
self.collection = None
# MongoDB.client = MongoDB.client or MongoClient(**MONGO_DB)
def __enter__(self):
with MongoDB._shared_mongo_client_lock:
if MongoDB._shared_mongo_client is None:
print("create client")
MongoDB._shared_mongo_client = MongoClient(**MONGO_DB)
MongoDB.num_users += 1
print("add", self._collection_name, MongoDB.num_users)
self.collection = MongoDB._shared_mongo_client[self._db_name][self._collection_name]
return self
def __exit__(self, *args, **kwargs):
self.collection = None
with MongoDB._shared_mongo_client_lock:
MongoDB.num_users -= 1
print("sub", self._collection_name, MongoDB.num_users)
if MongoDB.num_users is 0:
MongoDB._shared_mongo_client.close()
MongoDB._shared_mongo_client = None
print("client close")
# def use_collection(self, collection):
# return MongoDBCollection(self, collection)
def __getattr__(self, attr):
# print(attr, self.ATTRIBUTES_TO_PASS)
# raw_input()
if attr in self.ATTRIBUTES_TO_PASS:
return getattr(self.collection, attr)
else:
raise ValueError("")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment