dtmtec / restforce-bulk

Client for Salesforce Bulk API
MIT License
7 stars 45 forks source link

Support for multi-tenancy #3

Open corytheboyd opened 7 years ago

corytheboyd commented 7 years ago

I have a multi-tenant application, and need to create Batch Jobs for many different Salesforce organizations, which means many different Restforce clients. It would be great if the Job creation API supported that, as it's effectively hard-coded to Restforce::Bulk.client as far as I can tell.

From what I can tell, I can do it by basically re-implementing Restforce::Bulk::Job::create, but that isn't very clean:

# My own application code, used to get Restforce::Data::Client instance for a User.
restforce_client = User.first.get_restforce_client

bulk_client = Restforce::Bulk::Client.new(restforce_client)
job_builder = Restforce::Bulk::Builder::Xml.new(:query)
job_data = job_builder.job('Contact', 'CSV')
job_create_response = bulk_client.perform_request(:post, 'job', job_data)
job = Restforce::Bulk::Job.new(job_create_response.body.jobInfo)

Almost seems like that should be:

bulk_client = Restforce::Bulk::Client.new(restforce_client)
job = bulk_client.create_job(:query, 'Account', :csv)
corytheboyd commented 7 years ago

Here is the working code I came up with, basically avoiding the ::create methods exposed by Restforce::Bulk Job and Batch classes

# Collect Salesforce Contact IDs from our database
contact_ids = []
Person.find_in_batches do |people|
  contact_ids += people.map(&:sfdc_id).select { |id| id.starts_with?('003') }
end

# Create Bulk Job. Very long winded
restforce_client = User.first.get_restforce_client
bulk_client = Restforce::Bulk::Client.new(restforce_client)

job_builder = Restforce::Bulk::Builder::Xml.new(:query)
job_data = job_builder.job('Contact', 'CSV')
job_create_response = bulk_client.perform_request(:post, 'job', job_data)
job = Restforce::Bulk::Job.new(job_create_response.body.jobInfo)

batch_builder = Restforce::Bulk::Builder::Csv.new(:query)
batches = []

contact_ids.in_groups_of(200, false) do |contact_ids_group|
  contact_ids_range_string =
    contact_ids_group.map { |id| "'#{id}'" }.join(',')

  soql = <<-SOQL
  Select Id, AccountId FROM Contact
  SOQL

  add_batch_response = bulk_client.perform_request(
    :post,
    "job/#{job.id}/batch",
    soql,
    :csv
  )
  batch = Restforce::Bulk::Batch.new(add_batch_response.body.batchInfo)

  batches << batch
end

It's still pretty clean, to be honest. I still think the need stands to officially support this. I wouldn't mind taking a crack at it when I have some time.