Ejemplo n.º 1
0
        public async ValueTask <ModelWrapper> PullModel()
        {
            ConnectionWrapper GetConnection()
            {
                var fullList = new List <ConnectionWrapper>();

                while (connectionQueue.TryDequeue(out var connectionWrapper))
                {
                    if (connectionWrapper.Connection.IsOpen)
                    {
                        if (connectionWrapper.Increment() <= 16)
                        {
                            connectionQueue.Enqueue(connectionWrapper);
                            return(connectionWrapper);
                        }
                        else
                        {
                            connectionWrapper.Decrement();
                            fullList.Add(connectionWrapper);
                        }
                    }
                }
                foreach (var item in fullList)
                {
                    connectionQueue.Enqueue(item);
                }
                return(null);
            }

            if (!modelPool.TryDequeue(out var model))
            {
                var conn = GetConnection();
                if (conn == null && Interlocked.Increment(ref connectionCount) <= rabbitHost.MaxPoolSize)
                {
                    Task.Run(() =>
                    {
                        conn = new ConnectionWrapper
                        {
                            Client     = this,
                            Connection = _Factory.CreateConnection(rabbitHost.EndPoints)
                        };
                        conn.Increment();
                        connectionQueue.Enqueue(conn);
                    }).GetAwaiter().GetResult();
                }
                else
                {
                    Interlocked.Decrement(ref connectionCount);
                }
                if (conn != null)
                {
                    model = new ModelWrapper(conn, conn.Connection.CreateModel());
                    model.Model.ConfirmSelect();
                    modelList.Add(model);
                }
            }
            if (model == null)
            {
                var taskSource = new TaskCompletionSource <ModelWrapper>();
                modelTaskPool.Enqueue(taskSource);
                var cancelSource = new CancellationTokenSource(3000);
                cancelSource.Token.Register(() =>
                {
                    taskSource.SetException(new Exception("get rabbitmq's model timeout"));
                });
                model = await taskSource.Task;
            }
            return(model);
        }