how to avoid java.util.concurrent.ThreadPoolExecutor error with prisma - docker-compose

I am currently using Prisma on a large scale project. When performing a complex query, the Prisma cluster often errors out with the following message in the docker-logs (I'm redacting the error for readability):
{"key":"error/unhandled","requestId":"local:ck7ditux500570716cl5f8x3r","clientId":"default$default","payload":{"exception":"java.util.concurrent.RejectedExecutionException: Task slick.basic.BasicBackend$DatabaseDef$$anon$3#552b85a4 rejected from slick.util.AsyncExecutor$$anon$1$$anon$2#1d4391f7[Running, pool size = 9, active threads = 9, queued tasks = 1000, completed tasks = 43440]","query":"query ($where: TaskWhereUniqueInput!)
{\n task(where: $where) {\n workflow {\n tasks {\n id\n state\n parentReq\n frozen\n parentTask {\n id\n state\n }\n }\n }\n }\n}\n","variables":
"{\"where\":{\"id\":\"ck6twx873bs550874ne867066\"}}",
"code":"0","stack_trace":"java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)\\n
java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
...
"message":"Task slick.basic.BasicBackend$DatabaseDef$$anon$3#552b85a4 rejected from slick.util.AsyncExecutor$$anon$1$$anon$2#1d4391f7[Running, pool size = 9, active threads = 9, queued tasks = 1000, completed tasks = 43440]"}}
This is a frequent error when handling large queries. Has anyone come up with a way to configure Prisma or do internal batch operations to avoid this concurrency error?

Option 1:
I ran into this issue when running a prisma mutation in a loop with a lot of data which seemed to have created too many concurrent database operations.
My solution was to throttle the requests:
thingToLoop.map(() => {
await new Promise(resolve => setTimeout(resolve, 1000));
// Prisma operation here. Essentially this just makes the operation wait for one second between each operation.
})
Option 2
I've read other posts that say that you can set a limit to the number of concurrent connections as well.
See: https://v1.prisma.io/docs/1.25/prisma-server/database-connector-POSTGRES-jgfr/#overview
Essentially, this restricts the number of connections when too many are being created. See the following prisma config as an example:
PRISMA_CONFIG: |
managementApiSecret: __YOUR_MANAGEMENT_API_SECRET__
port: 4466
databases:
default:
connector: postgres
migrations: __ENABLE_DB_MIGRATIONS__
host: __YOUR_DATABASE_HOST__
port: __YOUR_DATABASE_PORT__
user: __YOUR_DATABASE_USER__
password: __YOUR_DATABASE_PASSWORD__
connectionLimit: __YOUR_CONNECTION_LIMIT__

Related

How to debug session leaking or close all sessions in python MongoDB?

It is my first time to use MongoDB to manage an image dataset(~10 million images).
My environment is MongoDB 5.0.6 with PymongoDB 4.0.2 and Python 3.9.6 on Ubuntu 18.04.
My dataset is accessing PyMongoDB and then it is used to train a DNN in Pytorch. My code warns at the begining:
UserWarning: MongoClient opened before fork.
Create MongoClient only after forking.
See PyMongo's documentation for details: https://pymongo.readthedocs.io/en/stable/faq.html#is-pymongo-fork-safe
(I check this url and get nothing. I think I indeed recreate the client each time when the class is instantiaed)
After running for a while, my code crashs, and exit
Unable to add session ID ffd152cf-97d3-454a-882a-c6fc693e2985 - 47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=
into the cache because the number of active sessions is too high,
full error:
{'ok': 0.0,
'errmsg': 'Unable to add session ID ffd152cf-97d3-454a-882a-c6fc693e2985 - 47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU= into the cache because the number of active sessions is too high',
'code': 261,
'codeName': 'TooManyLogicalSessions'}Unable to add session ID 85b35e6c-fc83-41d1-915b-83e6841c5467 - 47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU= into the cache because the number of active sessions is too high, full error: {'ok': 0.0, 'errmsg': 'Unable to add session ID 85b35e6c-fc83-41d1-915b-83e6841c5467 - 47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU= into the cache because the number of active sessions is too high',
'code': 261,
'codeName': 'TooManyLogicalSessions'}
As the error message, It seems I just opened too many sessions.
How can I check current active sessions in PyMongoDB? How can I close all sessions? Or how can I further debug this problem?
Thank you very much! My active sessions' number and my dataset code sample is offered as shown below:
1. Check the active sessions
My active sessions (db.serverStatus().connections) are indeed increasing:
{
current: 6,
available: 51194,
totalCreated: 199,
active: 2,
threaded: 6,
exhaustIsMaster: 0,
exhaustHello: 1,
awaitingTopologyChanges: 1
}
to
{
current: 156,
available: 51044,
totalCreated: 361,
active: 54,
threaded: 156,
exhaustIsMaster: 0,
exhaustHello: 51,
awaitingTopologyChanges: 51
}
and 5 minutes later, my program broke. (I don't know how to get this result from PymongoDB instead of mongosh. So I can only check it manually periodly. At this moment It seems there are still 51044 availiable, and should not be consumed up so quickly only in 5 minutes.)
2. my sample dataset code
like:
from torch.utils.data import Dataset
from pymongo import MongoClient
class MongoDataset(Dataset):
def __init__(self, dbName):
client = MongoClient(host = '127.0.0.1', port = 27017, connect=False)
db = client[dbName]
self.dataTable = db["dataTable"]
def getData(self, _id):
return self.dataTable.find_one({"_id" : _id})
def __len__(self):
return self.dataTable.estimated_document_count()
This class will be automatically forked, and recreated.

mongodb queries are very slow

I have a multi-threaded app that executes hundreds of transactions per second but after a while the performance drops and the queries are taking too long to execute. I have worked on optimising the connection with the following code to avoid errors, but this resulted in a poor performance.
My queries varies from inserts, delete and multi update; collections do not exceed 100,000 rows.
I have a cluster of 4 VMs for mongoldb each has 4 cores and 28GB of ram on Azure. I built the cluster using bitnami production (https://azure.microsoft.com/en-us/marketplace/partners/bitnami/production-mongodbdefault/)
private static MongoClientOptions options = MongoClientOptions.builder()
.connectionsPerHost(1000)
.threadsAllowedToBlockForConnectionMultiplier(15)
.connectTimeout(60 * 1000)
.maxWaitTime(60 * 1000)
.socketTimeout(60 * 1000)
.connectTimeout(60 * 1000)
.build();
I am not using any indexes and here is my app flow:
am using the db tales for queuing and processing msgs. Each job is saved in a separate collection, with a document for each msg that looks like this (status is 'ready' for the msgs at this stage):
{
"_id": ObjectId("57cd303743ffe80f3728fcf5"),
"_class": "com.mongodb.BasicDBObject",
"job_id": "57cd3031d9991f8639487013",
"priority": 1,
"title": "1",
"sender_id": "sender 1",
"account_id": "57c2d556d9991fbc15897275",
"schedule_date": ISODate("2016-09-05T08:43:00Z"),
"utf8": false,
"content": "text to be sent",
"number": "962799000001",
"status": "ready",
"user_id": "57c2d602d9991fbc1589727b",
"adv": true,
"number_of_sms_msgs": 1,
"uuid": "57cd3031d9991f8639487013_57cd303743ffe80f3728fcf5",
"msg_id": "1955559517"
}
Then I am moving batches from each job according to their priorities from status 'ready' to 'queued' and add them to on-memory queue to be processed:
List<DBObject> batch = scaffoldingRepository.findPageNoSort(dataType, page, next_batch_size, query, null);
if (batch != null && batch.size() > 0) {
BasicDBList ids = new BasicDBList();
for (final DBObject msg : batch) {
msg.put("status", "queued");
msg.put("uuid", job_id + "_" + msg.get("_id"));
ids.add(new ObjectId(msg.get("_id").toString()));
}
BasicDBObject search = new BasicDBObject();
search.put("_id", new BasicDBObject("$in", ids));
BasicDBObject update = new BasicDBObject();
update.put("$set", new BasicDBObject("status", "queued"));
scaffoldingRepository.updateObjects(search, update, dataType);
}
Then another thread sends the actual msgs from the on-memory queue and updates each msg's status separately (sent/failed); I add an index for this msg in a separate table so I can find it once the sender send me back the final status.
Finally I get a final result from the sender about the msg (delivered/undelivered) and I update this msg accordingly, then remove the index from (job_index) collection in the previous step.
==========================
UPDATE:======================
I noticed that I got this error in Java logs:
com.mongodb.MongoSocketReadTimeoutException: Timeout while receiving message
at com.mongodb.connection.InternalStreamConnection.translateReadException(InternalStreamConnection.java:475)
at com.mongodb.connection.InternalStreamConnection.receiveMessage(InternalStreamConnection.java:226)
at com.mongodb.connection.UsageTrackingInternalConnection.receiveMessage(UsageTrackingInternalConnection.java:105)
at com.mongodb.connection.DefaultConnectionPool$PooledConnection.receiveMessage(DefaultConnectionPool.java:438)
at com.mongodb.connection.WriteCommandProtocol.receiveMessage(WriteCommandProtocol.java:262)
at com.mongodb.connection.WriteCommandProtocol.execute(WriteCommandProtocol.java:104)
at com.mongodb.connection.UpdateCommandProtocol.execute(UpdateCommandProtocol.java:64)
at com.mongodb.connection.UpdateCommandProtocol.execute(UpdateCommandProtocol.java:37)
at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:168)
at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:289)
at com.mongodb.connection.DefaultServerConnection.updateCommand(DefaultServerConnection.java:143)
at com.mongodb.operation.UpdateOperation.executeCommandProtocol(UpdateOperation.java:76)
at com.mongodb.operation.BaseWriteOperation$1.call(BaseWriteOperation.java:142)
at com.mongodb.operation.BaseWriteOperation$1.call(BaseWriteOperation.java:134)
at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:232)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:223)
at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:134)
at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:61)
at com.mongodb.Mongo.execute(Mongo.java:827)
at com.mongodb.Mongo$2.execute(Mongo.java:810)
at com.mongodb.DBCollection.executeWriteOperation(DBCollection.java:333)
at com.mongodb.DBCollection.updateImpl(DBCollection.java:495)
at com.mongodb.DBCollection.update(DBCollection.java:455)
at com.mongodb.DBCollection.update(DBCollection.java:432)
at com.mongodb.DBCollection.update(DBCollection.java:522)
at com.mongodb.DBCollection.updateMulti(DBCollection.java:552)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
And here is my Mongodb config:
# mongod.conf
# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# Where and how to store data.
storage:
dbPath: /opt/bitnami/mongodb/data/db
journal:
enabled: true
#engine:
mmapv1:
smallFiles: true
# wiredTiger:
# where to write logging data.
systemLog:
destination: file
logAppend: true
path: /opt/bitnami/mongodb/logs/mongodb.log
# network interfaces
net:
port: 27017
bindIp: 0.0.0.0
unixDomainSocket:
enabled: true
pathPrefix: /opt/bitnami/mongodb/tmp
# replica set options
replication:
replSetName: replicaset
# process management options
processManagement:
fork: false
pidFilePath: /opt/bitnami/mongodb/tmp/mongodb.pid
# set parameter options
setParameter:
enableLocalhostAuthBypass: true
# security options
security:
authorization: disabled
#keyFile: replace_me
#profiling
#operationProfiling:
#slowOpThresholdMs: 100
#mode: slowOp
Few tips
-In MongoDB profiler did you check the slow running queries.
-Did you try indexing the documents (use inputs from above step)
-Which version of MongoDB are you using and which is the storage engine.
-Have you done replication of the server. If yes, please revisit the write concern part https://docs.mongodb.com/manual/core/replica-set-write-concern/
-Can you check whether mongodb in-memory implementation can help https://docs.mongodb.com/manual/core/inmemory/
-You can see few important tips here - https://docs.mongodb.com/manual/administration/analyzing-mongodb-performance/

MemoryStore leaking memory in SailsJs App

A few days ago, I run SailsJs app for the first time in production. This warning showed up.
Warning: connection.session() MemoryStore is not
designed for a production environment, as it will leak
memory, and will not scale past a single process.
I understand that a similar question has been asked and the answer seems to be periodically cleaning up sessionStore with code like.
function sessionCleanup() {
sessionStore.all(function(err, sessions) {
for (var i = 0; i < sessions.length; i++) {
sessionStore.get(sessions[i], function() {} );
}
});
}
How can I get reference to sessionStore in sails.js?
All what you need to do is just replace memory adapter in config/session.js with another adapter, Redis, for instance.
module.exports.session = {
secret: '<YOUR_SECRET>',
adapter: 'redis',
host: 'localhost',
port: 6379,
ttl: <REDIS_TTL_IN_SECONDS>,
pass: <REDIS_PASSWORD>
prefix: 'sess:'
};

* Unrecognized field at: database Did you mean?: - metrics - server - logging - DROPWIZARD

I cannot start my dropwizard application after add database details in my application configuration file (server.yml).
server.yml (app config file)
server:
applicationConnectors:
- type: http
port: 8080
adminConnectors:
- type: http
port: 9001
database:
# the name of your JDBC driver
driverClass: org.postgresql.Driver
# the username
user: dbuser
# the password
password: pw123
# the JDBC URL
url: jdbc:postgresql://localhost/database
# any properties specific to your JDBC driver:
properties:
charSet: UTF-8
# the maximum amount of time to wait on an empty pool before throwing an exception
maxWaitForConnection: 1s
# the SQL query to run when validating a connection's liveness
validationQuery: "/* MyService Health Check */ SELECT 1"
# the timeout before a connection validation queries fail
validationQueryTimeout: 3s
# the minimum number of connections to keep open
minSize: 8
# the maximum number of connections to keep open
maxSize: 32
# whether or not idle connections should be validated
checkConnectionWhileIdle: false
# the amount of time to sleep between runs of the idle connection validation, abandoned cleaner and idle pool resizing
evictionInterval: 10s
# the minimum amount of time an connection must sit idle in the pool before it is eligible for eviction
minIdleTime: 1 minute
As result of run dropwizard application I can see:
has an error:
* Unrecognized field at: database
Did you mean?:
- metrics
- server
- logging
In addition to code given by dropwizard example you need to add a setter for database property.
#Valid
#NotNull
#JsonProperty("database")
private DataSourceFactory database = new DataSourceFactory();
public DataSourceFactory getDataSourceFactory() {
return database;
}
public void setDatabase(DataSourceFactory database) {
this.database = database;
}
In your application configuration java file, you have to add the matching property for "database". If the properties you're specifying are the standard ones (which they look to be, good!) then you can keep with the DataSourceFactory type:
public class ExampleConfiguration extends Configuration {
#Valid
#NotNull
#JsonProperty
private DataSourceFactory database = new DataSourceFactory();
public DataSourceFactory getDataSourceFactory() {
return database;
}
public void setDatabase(DataSourceFactory database) {
this.database = database;
}
}
Example here: http://www.dropwizard.io/0.9.0/docs/manual/jdbi.html

Fiware Orion - pepProxy

i'm part of a team that is developing an application that uses the Fiware GE's has part of the Smart-AgriFood accelerator.
We are using the Orion Context Broker for gathering the data provided by the sensor network, and we intend to use the Pep-Proxy to authenticate the sensor node for access the Orion instance. We have tried the following pepProxy's:
https://github.com/telefonicaid/fiware-orion-pep
https://github.com/ging/fi-ware-pep-proxy
We only have success implementing the second (fi-ware-pep-proxy) implementation of the proxy. With the fiware-orion-pep we haven't been able to connect to the Keystone Global instance (account.lab.fi-ware.org), we have tried the account.lab... and the cloud.lab..., my question are:
1) is the keystone (IDM) instance for authentication the account.lab or the cloud.lab?? and what port's to use or address's?
2) is the fiware-orion-pep prepared for authenticate at the account.lab.fi-ware.org?? here is way i ask this:
This one works with the curl command at >> cloud.lab.fiware.org:4730/v2.0/tokens
{
"auth": {
"passwordCredentials": {
"username": "<my_user>",
"password": "<my_password>"
}
}
}'
This one does't work with the curl comand at >> account.lab.fi-ware.org:5000/v3/auth/tokens
{
"auth": {
"identity": {
"methods": [
"password"
],
"password": {
"user": {
"domain": {
"name": "<my_domain>"
},
"name": "<my_user>",
"password": "<my_password>"
}
}
}
} }'
3) what is the implementation that i should be using for authenticate the devices or other calls to the Orion instance???
Here are the configuration that i used:
fiware-orion-pep
config.authentication = {
checkHeaders: true,
module: 'keystone',
user: '<my_user>',
password: '<my_password>',
domainName: '<my_domain>',
retries: 3,
cacheTTLs: {
users: 1000,
projectIds: 1000,
roles: 60
},
options: {
protocol: 'http',
host: 'account.lab.fiware.org',
port: 5000,
path: '/v3/role_assignments',
authPath: '/v3/auth/tokens'
}
};
fi-ware-pep-proxy (this one works), i have set the listing port to 1026 at the source code
var config = {};
config.account_host = 'https://account.lab.fiware.org';
config.keystone_host = 'cloud.lab.fiware.org';
config.keystone_port = 4731;
config.app_host = 'localhost';
config.app_port = '10026';
config.username = 'pepProxy';
config.password = 'pepProxy';
// in seconds
config.chache_time = 300;
config.check_permissions = false;
config.magic_key = undefined;
module.exports = config;
Thanks in advance for the time ... :)
The are currently some differences in how both PEP Proxies authenticate and validate against the global instances, so they do not behave in exactly the same way.
The one in telefonicaid/fiware-orion-pep was developed to fulfill the PEP Proxy requirements (authentication and validation against a Keystone and Access Control) in individual projects with their own Keystone and Keypass (a flavour of Access Control) installations, and so it evolved faster than the one in ging/fi-ware-pep-proxy and in a slightly different direction. As an example, the former supports multitenancy using the fiware-service and fiware-servicepath headers, while the latter is transparent to those mechanisms. This development direction meant also that the functionality slightly differs from time to time from the one in the global instance.
That being said, the concrete answer:
- Both PEP Proxies should be able to contact the global instance. If one doesn't, please, fill a bug in the issues of the Github repository and we will fix it as soon as possible.
- The ging/fi-ware-pep-proxy was specifically designed for accessing the global instance, so you should be able to use it as expected.
Please, if you try to proceed with the telefonicaid/fiware-orion-pep take note also that:
- the configuration flag authentication.checkHeaders should be false, as the global instance does not currently support multitenancy.
- current stable release (0.5.0) is about to change to next version (probably today) so maybe some of the problems will solve with the update.
Hope this clarify some of your doubts.
[EDIT]
1) I have already install the telefonicaid/fiware-orion-pep (v 0.6.0) from sources and from the rpm package created following the tutorial available in the github. When creating the rpm package, this is created with the following name pep-proxy-0.4.0_next-0.noarch.rpm.
2) Here is the configuration that i used:
/opt/fiware-orion-pep/config.js
var config = {};
config.resource = {
original: {
host: 'localhost',
port: 10026
},
proxy: {
port: 1026,
adminPort: 11211
} };
config.authentication = {
checkHeaders: false,
module: 'keystone',
user: '<##################>',
password: '<###################>',
domainName: 'admin_domain',
retries: 3,
cacheTTLs: {
users: 1000,
projectIds: 1000,
roles: 60
},
options: { protocol: 'http',
host: 'cloud.lab.fiware.org',
port: 4730,
path: '/v3/role_assignments',
authPath: '/v3/auth/tokens'
} };
config.ssl = {
active: false,
keyFile: '',
certFile: '' }
config.logLevel = 'DEBUG'; // List of component
config.middlewares = {
require: 'lib/plugins/orionPlugin',
functions: [
'extractCBAction'
] };
config.componentName = 'orion';
config.resourceNamePrefix = 'fiware:';
config.bypass = false;
config.bypassRoleId = '';
module.exports = config;
/etc/sysconfig/pepProxy
# General Configuration
############################################################################
# Port where the proxy will listen for requests
PROXY_PORT=1026
# User to execute the PEP Proxy with
PROXY_USER=pepproxy
# Host where the target Context Broker is located
# TARGET_HOST=localhost
# Port where the target Context Broker is listening
# TARGET_PORT=10026
# Maximum level of logs to show (FATAL, ERROR, WARNING, INFO, DEBUG)
LOG_LEVEL=DEBUG
# Indicates what component plugin should be loaded with this PEP: orion, keypass, perseo
COMPONENT_PLUGIN=orion
#
# Access Control Configuration
############################################################################
# Host where the Access Control (the component who knows the policies for the incoming requests) is located
# ACCESS_HOST=
# Port where the Access Control is listening
# ACCESS_PORT=
# Host where the authentication authority for the Access Control is located
# AUTHENTICATION_HOST=
# Port where the authentication authority is listening
# AUTHENTICATION_PORT=
# User name of the PEP Proxy in the authentication authority
PROXY_USERNAME=XXXXXXXXXXXXX
# Password of the PEP Proxy in the Authentication authority
PROXY_PASSWORD=XXXXXXXXXXXXX
In the files above i have tried the following parameters:
Keystone instance: account.lab.fiware.org or cloud.lab.fiware.org
User: pep or pepProxy or "user from fiware account"
Pass: pep or pepProxy or "user password from account"
Port: 4730, 4731, 5000
The result it's the same as before... the telefonicaid/fiware-orion-pep is unable to authenticate:
log file at /var/log/pepProxy/pepProxy
time=2015-04-13T14:49:24.718Z | lvl=ERROR | corr=71a34c8b-10b3-40a3-be85-71bd3ce34c8a | trans=71a34c8b-10b3-40a3-be85-71bd3ce34c8a | op=/v1/updateContext | msg=VALIDATION-GEN-003] Error connecting to Keystone authentication: KEYSTONE_AUTHENTICATION_ERROR: There was a connection error while authenticating to Keystone: 500
time=2015-04-13T14:49:24.721Z | lvl=DEBUG | corr=71a34c8b-10b3-40a3-be85-71bd3ce34c8a | trans=71a34c8b-10b3-40a3-be85-71bd3ce34c8a | op=/v1/updateContext | msg=response-time: 50745 statusCode: 500
result from the client console
{
"message": "There was a connection error while authenticating to Keystone: 500",
"name": "KEYSTONE_AUTHENTICATION_ERROR"
}
I'm doing something wrong here??