All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.thunderz99.cosmos.impl.cosmosdb.CosmosImpl Maven / Gradle / Ivy

There is a newer version: 0.7.11
Show newest version
package io.github.thunderz99.cosmos.impl.cosmosdb;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

import com.azure.cosmos.CosmosClient;
import com.azure.cosmos.CosmosClientBuilder;
import com.azure.cosmos.models.CosmosContainerProperties;
import io.github.thunderz99.cosmos.Cosmos;
import io.github.thunderz99.cosmos.CosmosBuilder;
import io.github.thunderz99.cosmos.CosmosDatabase;
import io.github.thunderz99.cosmos.CosmosException;
import io.github.thunderz99.cosmos.dto.CosmosContainerResponse;
import io.github.thunderz99.cosmos.dto.UniqueKeyPolicy;
import io.github.thunderz99.cosmos.util.Checker;
import io.github.thunderz99.cosmos.util.ConnectionStringUtil;
import io.github.thunderz99.cosmos.util.LinkFormatUtil;
import io.github.thunderz99.cosmos.util.UniqueKeyUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/***
 * class that represent a cosmos account
 *
 * 
 * Usage: var cosmos = new
 * Cosmos("AccountEndpoint=https://xxx.documents.azure.com:443/;AccountKey=xxx==;");
 * var db = cosmos.getDatabase("Database1");
 *
 * //Then use db to do CRUD / query db.upsert("Users", user);
 * 
* */ public class CosmosImpl implements Cosmos { private static Logger log = LoggerFactory.getLogger(CosmosImpl.class); CosmosClient clientV4; String account; public static final String COSMOS_SDK_V4_ENABLE = "COSMOS_SDK_V4_ENABLE"; public static final String ETAG = "_etag"; public CosmosImpl(String connectionString) { this(connectionString, null); } public CosmosImpl(String connectionString, List preferredRegions) { Pair pair = ConnectionStringUtil.parseConnectionString(connectionString); var endpoint = pair.getLeft(); var key = pair.getRight(); log.info("COSMOS_SDK_V4_ENABLE is enabled for endpoint:{}", endpoint); this.clientV4 = new CosmosClientBuilder() .endpoint(endpoint) .key(key) .preferredRegions(preferredRegions) .consistencyLevel(com.azure.cosmos.ConsistencyLevel.SESSION) .contentResponseOnWriteEnabled(true) .buildClient(); this.account = extractAccountName(endpoint); Runtime.getRuntime().addShutdownHook(new Thread(() -> { this.clientV4.close(); })); } /** * Get a CosmosDatabase object by name * * @param db database name * @return CosmosDatabase instance */ public CosmosDatabase getDatabase(String db) { Checker.checkNotEmpty(db, "db"); return new CosmosDatabaseImpl(this, db); } /** * extract the Cosmos DB 's account name from the endpoint * * @param endpoint the endpoint for Cosmos DB * @return account name */ static String extractAccountName(String endpoint) { try { var uri = new URI(endpoint); String host = uri.getHost(); return StringUtils.isEmpty(host) ? "" : host.split("\\.")[0]; } catch (URISyntaxException e) { log.error("Error parsing endpoint URI", e); return ""; } } /** * Create the db and coll if not exist. Coll creation will be skipped if empty. uniqueKeyPolicy can be specified. * * @param db database name * @param coll collection name * @param uniqueKeyPolicy unique key policy for the collection * @return CosmosDatabase instance * @throws CosmosException Cosmos client exception */ public CosmosDatabase createIfNotExist(String db, String coll, UniqueKeyPolicy uniqueKeyPolicy) throws CosmosException { Checker.checkNotBlank(db, "Database name"); this.clientV4.createDatabaseIfNotExists(db); log.info("created database:{}, account:{}", db, account); if (StringUtils.isBlank(coll)) { //do nothing } else { var cosmosDatabase = this.clientV4.getDatabase(db); var containerProperties = new CosmosContainerProperties(coll, "/" + getDefaultPartitionKey()); var keyList = uniqueKeyPolicy.uniqueKeys; if (CollectionUtils.isNotEmpty(keyList)) { containerProperties.setUniqueKeyPolicy(UniqueKeyUtil.toCosmosUniqueKeyPolicy(uniqueKeyPolicy)); } cosmosDatabase.createContainerIfNotExists(containerProperties); } return new CosmosDatabaseImpl(this, db); } /** * Create the db and coll if not exist. Coll creation will be skipped if empty. * *

* No uniqueKeyPolicy will be used. *

* * @param db database name * @param coll collection name * @return CosmosDatabase instance * @throws CosmosException Cosmos client exception Cosmos client exception */ public CosmosDatabase createIfNotExist(String db, String coll) throws CosmosException { return createIfNotExist(db, coll, getDefaultUniqueKeyPolicy()); } /** * Delete a database by name * * @param db database name * @throws CosmosException Cosmos client exception */ public void deleteDatabase(String db) throws CosmosException { if (StringUtils.isEmpty(db)) { return; } var cosmosDatabase = this.clientV4.getDatabase(db); try { cosmosDatabase.delete(); } catch (com.azure.cosmos.CosmosException ce) { if (isResourceNotFoundException(ce)) { log.info("delete Database not exist. Ignored:{}, account:{}", LinkFormatUtil.getDatabaseLink(db), this.account); } else { throw ce; } } } /** * Delete a collection by db name and coll name * * @param db database name * @param coll collection name * @throws CosmosException Cosmos client exception */ public void deleteCollection(String db, String coll) throws CosmosException { var cosmosDatabase = this.clientV4.getDatabase(db); var container = cosmosDatabase.getContainer(coll); try { container.delete(); } catch (com.azure.cosmos.CosmosException ce) { // If not exist if (isResourceNotFoundException(ce)) { log.info("delete Collection not exist. Ignored:{}, account:{}", LinkFormatUtil.getCollectionLink(db, coll), this.account); } else { // Throw any other Exception throw ce; } } } /** * Read the document collection obj by dbName and collName. * * @param db dbName * @param coll collName * @return CosmosContainerResponse obj * @throws CosmosException when client exception occurs */ public CosmosContainerResponse readCollection(String db, String coll) throws CosmosException { var database = this.clientV4.getDatabase(db); try { var response = database.getContainer(coll).read(); var policy = UniqueKeyUtil.toCommonUniqueKeyPolicy(response.getProperties().getUniqueKeyPolicy()); return new CosmosContainerResponse(coll, policy); } catch (com.azure.cosmos.CosmosException ce) { if (isResourceNotFoundException(ce)) { return null; } throw ce; } } /** * Get Official cosmos db sdk(v4)'s CosmosClient instance * * @return official cosmosdb sdk client(v4) */ public CosmosClient getClientV4() { return this.clientV4; } /** * return the default unique key policy * * @return default unique key policy */ public static UniqueKeyPolicy getDefaultUniqueKeyPolicy() { var uniqueKeyPolicy = new UniqueKeyPolicy(); return uniqueKeyPolicy; } public static boolean isResourceNotFoundException(Exception e) { if (e instanceof CosmosException) { var ce = (CosmosException) e; return ce.getStatusCode() == 404; } return StringUtils.contains(e.getMessage(), "Resource Not Found") ? true : false; } /** * get the default partition key * * @return default partition key */ public static String getDefaultPartitionKey() { return "_partition"; } public String getAccount() throws CosmosException { return account; } @Override public String getDatabaseType() { return CosmosBuilder.COSMOSDB; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy