0

This is a continuation of a previous SO question I asked.

I'm trying to create an ObjectPool of my FTP Clients. FTP Clients are expensive to use because of the "connection" step. So I thought -> let's pool them so after the initial connection step, we can reuse these connected FTP clients!

I'm now trying to use the Microsoft.Extensions.ObjectPool nuget/library to enable my class library to create an ObjectPool. I also wish to make sure that I can only ever have 100 FTP clients at most because the destination FTP server has a max of 100 client connects at the same time.

Given the following MyFtpClient class, I'm not sure how to do this:

public class MyFtpClient : IMyFtpClient
{
    private readonly RealFtpClient _realFtpClient;

    public MyFtpClient(string host, string username, string password)
    {
        // initialize FTP client
        _realFtpClient = new RealFtpClient(host, username, password);
    }

    public async Task UploadFileAsync(Stream someFile, CancellationToken ct)
    {
        // upload file using FTP client
        await _realFtpClient.UploadFile(someFile, ct);
    }
}

I thought I might try something like this:

var objectPool = new DefaultObjectPool<MyFtpClient>(new DefaultPooledObjectPolicy<MyFtpClient>(), 100);

but that doesn't work because MyFtpClient is not parameterless.

For more context, I'm grabbing messages from a Queue and then pushing up the message context to the ftp server. I pull down 100 messages at a time. (if there's less than 100 messages in the queue, then it will only return whatever the full amount happens to be .. like 20 msgs or 55 msgs, etc).

so for each message in the GetMessagesFromQueue:

  • Get a MyFtpClient
  • get a Task to Upload message to ftp server.
  • await Task.WhenAll(tasks); <-- now await all those uploads, which would be a max of 100.

What can I try next?

halfer
  • 19,824
  • 17
  • 99
  • 186
Pure.Krome
  • 84,693
  • 113
  • 396
  • 647
  • You could create your own `DefaultPooledObjectPolicy`-derived class that overrides `Create` to create new MyFtpClient or `RealFtpClient` instances – Panagiotis Kanavos Mar 01 '23 at 15:50

1 Answers1

2

You can create your own custom PooledObjectPolicy that implements IPooledObjectPolicy<MyFtpClient> and that takes the connection details in its constructor, calling the Create() method.

public class MyFtpClientPooledObjectPolicy : IPooledObjectPolicy<MyFtpClient>
{
    private string _host;
    private string _username;
    private string _password;
    
    public MyFtpClientPooledObjectPolicy(
        string host, string username, string password)
    {
        _host = host;
        _username = username;
        _password = password;
    }
    
    public MyFtpClient Create()
    {
        return new MyFtpClient(_host, _username, _password);
    }

    public bool Return(MyFtpClient obj)
    {
        return true;
    }
}

This allows you to create your pool as follows:

var host = string.Empty;
var username = string.Empty;
var password = string.Empty;
var objectPool = new DefaultObjectPool<MyFtpClient>(
    new MyFtpClientPooledObjectPolicy(host, username, password), 100);
David L
  • 32,885
  • 8
  • 62
  • 93