/**
 *
 */
package nl.kataru.pvdataloader;

import java.net.UnknownHostException;

import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoException;
import com.mongodb.ServerAddress;

/**
 * @author morten
 *
 */
public class MongoPVDataRepository implements PVDataRepository {
	private static final String COLLECTION = "inverterdata";
	private MongoClient mongoClient;
	private DB database;

	/**
	 * Initialize the Mongo DB client with the given address, port and database name.
	 *
	 * @param mongodb_address
	 * @param mongodb_port
	 * @param database_name
	 *
	 * @throws RuntimeException
	 *             in case the client cannot be initialized correctly.
	 */
	public MongoPVDataRepository(String mongodb_address, int mongodb_port, String database_name) {

		try {
			final MongoClientOptions options = MongoClientOptions.builder().build();
			mongoClient = new MongoClient(new ServerAddress(mongodb_address, mongodb_port), options);

			database = mongoClient.getDB(database_name);
		} catch (final UnknownHostException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Save the given object. If an error occurs while storing the object in MongoDB this method will retry
	 * indefinitely until it succeeds, or until the program is interrupted.
	 *
	 * @see nl.kataru.pvdataloader.PVDataRepository#save(java.lang.String)
	 */
	@Override
	public void save(DBObject object) {
		final DBCollection collection = database.getCollection(COLLECTION);

		boolean success = false;
		while (!success) {
			try {
				collection.insert(object);
				success = true;
			} catch (final MongoException exception) {
				System.err.println("Error while inserting data in mongodb: " + exception.getMessage());
				try {
					Thread.sleep(30000); // Sleep for 30 seconds and try again
				} catch (final InterruptedException interruptedException) {
					System.err.println("Error while sleeping: " + interruptedException.getMessage());
				}
			}
		}
	}

	/**
	 * Gracefully close the Mongo DB Client.
	 *
	 * @see nl.kataru.pvdataloader.PVDataRepository#close()
	 */
	@Override
	public void close() {
		mongoClient.close();
	}

}

@@ -76,16 +76,50 @@
 ption;%0A%0A
+import com.mongodb.BasicDBObject;%0A
 import c
@@ -187,32 +187,74 @@
 ngodb.DBObject;%0A
+import com.mongodb.DuplicateKeyException;%0A
 import com.mongo
@@ -472,16 +472,171 @@
 itory %7B%0A
+%09private static final int RETRY_DELAY = 30000;%09// Retry delay in milliseconds. If an insertion in the database fails, try again after this amount of time.%0A
 %09private
@@ -1339,16 +1339,435 @@
 _name);%0A
+%0A%09%09%09// create a unique index on the collection for the timestamp and serialnumber (each inverter should only log one item per time unit)%0A%09%09%09final DBCollection collection = database.getCollection(COLLECTION);%0A%09%09%09final DBObject index = new BasicDBObject().append(%22serialnumber%22, 1).append(%22timestamp%22, 1);%0A%09%09%09final DBObject constraints = new BasicDBObject(%22unique%22, true);%0A%09%09%09collection.createIndex(index, constraints);%0A%0A
 %09%09%7D catc
@@ -2240,22 +2240,19 @@
 ean 
-success = fals
+retry = tru
 e;%0A%09
@@ -2263,16 +2263,13 @@
 le (
-!success
+retry
 ) %7B%0A
@@ -2316,21 +2316,183 @@
 %09%09%09%09
-success = tru
+retry = false;%0A%09%09%09%7D catch (final DuplicateKeyException exception) %7B%0A%09%09%09%09System.err.println(%22Warning, could not insert data, duplicate key exists: %22 + object);%0A%09%09%09%09retry = fals
 e;%0A%09
@@ -2624,24 +2624,91 @@
 Message());%0A
+%09%09%09%09System.err.println(%22Trying again in %22 + RETRY_DELAY + %22 ms.%22);%0A
 %09%09%09%09try %7B%0A%09%09
@@ -2723,21 +2723,27 @@
 d.sleep(
-30000
+RETRY_DELAY
 ); // Sl

Add unique index for timestamp and serial number and handle duplicate key exceptions