Creating Connection Pool and using the connection pool in JanusGraph - gremlin

I am using JanusGraph. How do I create a connection pool while connecting to JanusGraph remotely and then using the pool to borrow the connection?
right now I am doing something like
private static void init() {
String uri = "localhost";
int poolSize = 5;
graph = JanusGraphFactory.open("inmemory");
cluster = Cluster.build()
.addContactPoint(uri)
.port(8182)
.serializer(new GryoMessageSerializerV1d0(GryoMapper.build().addRegistry(JanusGraphIoRegistry.getInstance())))
.maxConnectionPoolSize(poolSize)
.minConnectionPoolSize(poolSize)
.create();
gts = graph
.traversal()
.withRemote(DriverRemoteConnection.using(cluster));
}
this init method is initialized once. and then anyone who requires connection simple calls the below method
public GraphTraversalSource getConnection() {
return gts.clone();
}
Please note that withRemote() method is being deprecated now. I am not sure am I doing it correctly?

I think you're confusing some concepts. You only need to use the TinkerPop driver (i.e. Cluster) if you are connecting to a Graph instance remotely. In your case you're creating your JanusGraph instance locally, so you can simply do graph.traversal() and start writing Gremlin. If you hosted your JanusGraph instance in Gremlin Server on the other hand, then you would need to use the withRemote() option. As you mention withRemote() in the fashion you are calling it is deprecated, but the javadoc mentions the new method which can also be found in the documentation:
import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
GraphTraversalSource g = traversal().withRemote(DriverRemoteConnection.using(cluster));
To understand all the different options for connecting to a Graph instance I'd suggest reading this section of TinkerPop's Reference Documentation.

Related

Connecting JanusGraph with springboot

Connect JanusGraph using Springboot and perform some CRUD operations. Gremlin Server is started at 8182.
Tried with providing absolute path to read properties file.
is anything wrong with code or property file? need to configure anything in gremlin server yaml file?
getting error
"java.lang.ClassNotFoundException: org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IoStep"
java.lang.ClassNotFoundException: org.apache.tinkerpop.gremlin.process.traversal.step.filter.NoneStep
Dependencies:
<dependency>
<groupId>org.janusgraph</groupId>
<artifactId>janusgraph-core</artifactId>
<version>0.5.2</version>
</dependency>
<dependency>
<groupId>org.janusgraph</groupId>
<artifactId>janusgraph-berkeleyje</artifactId>
<version>0.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.tinkerpop</groupId>
<artifactId>gremlin-driver</artifactId>
<version>3.2.9</version>
</dependency>
Graph class
#RestController
public class GraphT {
#GetMapping("/test")
String all() {
Graph graph = JanusGraphFactory.open("conf/janusgraph-berkeleyje.properties");
GraphTraversalSource g = graph.traversal();
//Add one vertex
g.addV("person").property("name", "bob").property("age", 27).iterate();
//Confirm change
g.tx().commit();
//Try issuing a query to retrieve the value
List<Map<String, Object>> result = g.V().valueMap("name", "age").toList();
//The return value is[{name: ["bob"], age: [27]}]Should be returned
for(Map<String, Object> vertex : result){
//vertex is{name:["bob"], age: [27]}Should be
ArrayList<String> names = (ArrayList<String>)vertex.get("name"); // ["bob"]Get
ArrayList<Integer> ages = (ArrayList<Integer>)vertex.get("age"); // [27]Get
String name = names.get(0); //"bob"Get
Integer age = ages.get(0); //Get 27
System.out.printf("name: %s, age: %s\n", name, age);
}
//Try issuing a query to retrieve the number of vertices
Long count = g.V().count().next();
System.out.printf("vertex count is %d\n", count);
try {
graph.close();
} catch (Exception ex) {
//deal with it
}
return " some result ";
}
}
3. config file
gremlin.graph=org.janusgraph.core.JanusGraphFactory
storage.backend=berkeleyje
storage.directory=../db/berkeley
I see two different problems in the setup you described:
Incompatible library versions
You are mixing versions of JanusGraph and TinkerPop that are not compatible with another.
If you want to use version 0.6.1 of janusgraph-berkeleyje, then you should also use the same version for janusgraph-core. The newest version is 0.6.2 right now by the way so you may just want to use that version.
But more importantly: Versions 0.6.* of JanusGraph are compatible with versions 3.5.* of TinkerPop, but you are using version 3.2.9 of gremlin-driver.
The JanusGraph release notes show which versions each JanusGraph release is compatible with. For 0.6.2 of JanusGraph, compatibility is tested with TinkerPop version 3.5.3, so I would use that version.
JanusGraph Server vs Embedded JanusGraph
Apart from that, you say that you have started Gremlin Server, but then you are not connecting to that server in your Java code, but instead you are starting a local JanusGraph instance which directly uses Berkeley via JanusGraphFactory.open(). This means that your Java application will not use the started Gremlin Server at all.
You should decide whether you want to run JanusGraph as a server to which you can connect from various applications or using JanusGraph as a library which directly uses the storage backend.
You can read more about this difference in the section Deployment Scenarios of the JanusGraph documentation. Embedded JanusGraph is the scenario where JanusGraph is used as a library.
If you want to use JanusGraph Server (which is the Gremlin Server configured for JanusGraph) and connect to that remotely from your Java application, then the section Connecting from Java of the documentation explains how that can be done.

How to get DynamoDB from DynamoDB local creation

Trying to write integration test for my logic, using recommended way to launch dynamoDB local:
final String port = getAvailablePort();
this.server = ServerRunner.createServerFromCommandLineArgs(new String[] { "-inMemory", "-port", port });
server.start();
amazonDynamoDB = AmazonDynamoDBClientBuilder.standard().withEndpointConfiguration(
// we can use any region here
new AwsClientBuilder.EndpointConfiguration("http://localhost:" + port, "us-west-2")).build();
I am planning to use com.amazonaws.services.dynamodbv2.document.DynamoDB in my production code to read/write from dynamo. I am looking to reuse some production dynamo-write code to setup testing data, hence, I will need com.amazonaws.services.dynamodbv2.document.DynamoDB object. However dynamo local setup above only give com.amazonaws.services.dynamodbv2.AmazonDynamoDB, any clue/suggestion on how to convert?
You can create an instance of DynamoDB from a AmazonDynamoDB using this constructor which has a signature of DynamoDB(AmazonDynamoDB client).

Optimize connection to SQLite DB using EF Core in UWP app

I'm currently working on a C# UWP application that runs on Windows 10 IoT Core OS on an ARM processor. For this application, I am using a SQLite DB for my persistence, with Entity Framework Core as my ORM.
I have created my own DBContext and call the Migrate function on startup which creates my DB. I can also successfully create a DBContext instance in my main logic which can successfully read/write data using the model. All good so far.
However, I've noticed that the performance of creating a DbContext for each interaction with the DB is painfully slow. Although I can guarantee that only my application is accessing the database (I'm running on custom hardware with a controlled software environment), I do have multiple threads in my application that need to access the database via the DbContext.
I need to find a way to optimize the connection to my SQLite DB in a way that is thread safe in my application. As I mentioned before, I don't have to worry about any external applications.
At first, I tried to create a SqliteConnection object externally and then pass it in to each DbContext that I create:
_connection = new SqliteConnection(#"Data Source=main.db");
... and then make that available to my DbContext and use in in the OnConfiguring override:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite(_connection);
}
... and then use the DbContext in my application like this:
using (var db = new MyDbContext())
{
var data = new MyData { Timestamp = DateTime.UtcNow, Data = "123" };
db.MyData.Add(data);
db.SaveChanges();
}
// Example data read
MyDataListView.ItemsSource = db.MyData.ToList();
Taking the above approach, I noticed that the connection is closed down automatically when the DbContext is disposed, regardless of the fact that the connection was created externally. So this ends up throwing an exception the second time I create a DbContext with the connection.
Secondly, I tried to create a single DbContext once statically and share it across my entire application. So instead of creating the DbContext in a using statement as above, I tried the following:
// Where Context property returns a singleton instance of MyDbContext
var db = MyDbContextFactory.Context;
var data = new MyData { Timestamp = DateTime.UtcNow, Data = "123" };
db.MyData.Add(data);
db.SaveChanges();
This offers me the performance improvements I hoped for but I quickly realized that this is not thread safe and wider reading has confirmed that I shouldn't do this.
So does anyone have any advice on how to improve the performance when accessing SQLite DB in my case with EF Core and a multi-threaded UWP application? Many thanks in advance.
Secondly, I tried to create a single DbContext once statically and share it across my entire application. So instead of creating the DbContext in a using statement as above, I tried the following...This offers me the performance improvements I hoped for but I quickly realized that this is not thread safe and wider reading has confirmed that I shouldn't do this.
I don't know why we shouldn't do this. Maybe you can share something about what you read. But I think, you can make the DBContext object global and static and when you want to do CRUD, you can do it in main thread like this:
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
//App.BloggingDB is the static global DBContext defined in App class
var blog = new Blog { Url = NewBlogUrl.Text };
App.BloggingDB.Add(blog);
App.BloggingDB.SaveChanges();
});
But do dispose the DBContext at a proper time as it won't automatically get disposed.

Oracle Coherence

I'm new to Oracle Coherence. I read the documentation and done the hands-on using the command prompt. I've no issues in understanding. Then I downloaded the eclipse with oracle coherence tools. I created the application client for the oracle coherence as given below
http://docs.oracle.com/cd/E18686_01/coh.37/e18692/installjdev.htm
I ran the same. It was working fine as I did in my console application. Then I created a new project in the same workspace, created a main class accessed the named cache, put and retrieved some values using the below code,
package coherenceClient;
import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;
public class Main {
public static void main(String[] args) {
NamedCache cache = CacheFactory.getCache("myCache");
cache.put("MyFirstCacheObject", "This is my first Cache Object");
System.out.println(cache.get("MyFirstCacheObject"));
}
}
I retieved the same value. Then I created another class tried retrieved the same value but it was returning null. Is there are any mistakes in the code?
package coherenceClient;
import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;
public class Recevier {
public static void main(String[] args) {
NamedCache cache = CacheFactory.getCache("myCache");
System.out.println(cache.get("MyFirstCacheObject"));
}
}
If the coherence cache resides in the JVM (it is not ran as standalone server), then all the data get discarded after your program finishes (you use in-memory storage). Try to put Thread.sleep(200000); to the end of the first program and then run the second instance within the timeout.
In the command prompt you have started the server(as stand-alone) and the clients have joined the server. So all the data in the cache will be available until the server stops, even if the client which inserted the data into the cache leaves the server session.
But in the above case, the coherence cache resides in the JVM(Eclipse) itself and not as stand alone server. So you are getting null value when the program exists.
When you run the second JVM check the original coherence cache server node stdout to see if you actually see the new member joining in the cluster (check the MemberSet). You might just be running two separate JVMs which are completely unaware of each other; hence CacheFactory.getCache("myCache") is creating the cache in each JVM.
The way to go around this is to use cache-server.cmd to start a coherence cache server and then run your eclipse program with a distributed/partitioned or replicated scheme. That way, even when your program exits, the actual data would be live in the the coherence cache server for the second JVM to retrieve when it joins the "same cluster".

asp.net webservice OnUnload?

I'm creating a web service which has a number of methods, all of which make use of a SqlConnection. It seems logical that I would declare a class level connection and initialise it in the web service constructor.
Problem is I cannot find a definitive way to release the connection when the web service call completes, so I have a connection leak. I've tried overriding the Dipose() method but it doesn't get called in a reasonable timeframe (actually not at all in my testing). For good measure I also tried attaching a handler to the Disposed() event but as expected same problem.
Is there nothing similar to Page.OnUnload for web service classes? It seems hard to believe I would have to establish a separate connection in every individual method.
Any suggestions?
It seems logical that I would declare a class level connection and initialise it in the web service constructor.
No, this doesn't seem logical at all. ADO.NET uses a connection pooling so that you don't need to do this. This connection pool is per connection string per application domain.
So you could simply draw a new connection from the pool in each web method and return it to the pool at the end (the using statements will take care of this):
[WebMethod]
public void Foo()
{
// Here you are NOT creating a new connection to the database
// you are just drawing one from the connection pool
using (var conn = new SqlConnection(SomeConnectionString))
using (var cmd = conn.CreateCommand())
{
// Here you are NOT opening a new connection to the database
conn.Open();
cmd.CommandText = "SELECT id FROM foo";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// do something with the results
}
}
} // Here you are NOT closing the connection, you are just returning it to the pool
}
So here's an advice: don't try to manage connections manually by using some class fields, static fields, ... Leave this management to ADO.NET as it does it better.
Remark: The code I've shown usually resides in a data access layer which is called by the web method.

Resources