Newer Version Available
PackageSubscriber
Represents an installation of a package in an org. This object contains
installation information for managed or unlocked packages developed in the org you’re
logged in to.
One record is created per installation. For example, if 5 orgs installed 2 packages, 10 records are created.
Supported Calls
describeSObjects(), query(), retrieve()
Fields
| Field Name | Details |
|---|---|
| InstalledStatus |
|
| InstanceName |
|
| MetadataPackageId |
|
| MetadataPackageVersionId |
|
| OrgKey |
|
| OrgName |
|
| OrgStatus |
|
| OrgType |
|
| ParentOrg |
|
Usage
Here are examples of the types of API queries you can perform.
| Query | String |
|---|---|
| Get all package subscriber orgs with a specific package ID | SELECT Id, OrgKey, OrgStatus, OrgName, OrgType FROM PackageSubscriber WHERE MetadataPackageVersionId = '04t...' |
| Get all package subscriber orgs that have an installed package created by the org you’re logged in to | SELECT Id, OrgKey, OrgStatus, OrgName, OrgType FROM PackageSubscriber WHERE InstalledStatus = 'i' |
Filter PackageSubscriber Objects by Instance
If you have packages with many subscribers, querying PackageSubscriber objects can take a while. To improve query performance, add filters to your PackageSubscriber queries, such as an InstanceName filter. InstanceName is a field that represents the instance that the subscriber org is hosted on.
- Get the org’s package and the latest released version of the
package.
1/** 2* Get the MetadataPackage object corresponding to this org's managed package 3*/ 4public MetadataPackage getMetadataPackage() throws ConnectionException { 5 // retrieve the managed package, which won’t have an empty namespace 6 QueryResult result = conn.query("select id from MetadataPackage where namespaceprefix <> ''"); 7 8 return (MetadataPackage) result.getRecords()[0]; 9} 10 11/** 12* Get the latest MetadataPackageVersion object of the given MetadataPackage 13*/ 14public MetadataPackageVersion getLatestMetadataPackageVersion(MetadataPackage metadataPackage) 15throws ConnectionException { 16 // get the latest released version of the given package 17 String query = "Select id, ReleaseState, MajorVersion, MinorVersion, PatchVersion, 18MetadataPackageId" 19 + " From MetadataPackageVersion" 20 + " Where MetadataPackageId = '%s' and ReleaseState = 'Released'" 21 + " Order by majorversion desc, minorversion desc, patchversion desc"; 22 23 QueryResult result = conn.query(String.format(query, metadataPackage.getId())); 24 25 return (MetadataPackageVersion) result.getRecords()[0]; 26} - Get eligible subscribers. The following query strings and methods are modified
to allow querying for PackageSubscribers filtered by an
instance.
1static final String PACKAGE_SUBSCRIBER_ORG_KEY_QUERY = "Select OrgKey from PackageSubscribers where OrgStatus = 'Active'" 2 + " and InstalledStatus = 'I'" 3 + " and InstanceName = '%s'"; // placeholder for instance values 4 5static final String METADATA_PACKAGE_VERSION_QUERY = "Select Id, Name, ReleaseState, (%s) from MetadataPackageVersion" 6 + " where MetadataPackageId = '%s' AND ReleaseState = 'Released'" 7 + " AND (MajorVersion < %s OR (MajorVersion = %s and MinorVersion < %s)" 8 + " OR (MajorVersion = %s and MinorVersion = %s and PatchVersion < %s))"; 9 10/** 11* Get all PackageSubscribers on the given instance that are eligible to upgrade to the given 12* MetadataPackageVersion 13*/ 14public PackageSubscriber[] getEligibleSubscriberIds(MetadataPackageVersion version, String instanceName) throws ConnectionException { 15 String allPackageId = version.getMetadataPackageId(); 16 Integer major = version.getMajorVersion(); 17 Integer minor = version.getMinorVersion(); 18 Integer patch = version.getPatchVersion(); 19 20 return getEligibleSubscriberIds(major, minor, patch, allPackageId, instanceName); 21}1public PackageSubscriber[] getEligibleSubscriberIds(Integer major, Integer minor, Integer patch, String packageId, String instanceName) throws ConnectionException { 2 String subscriberQuery = String.format(PACKAGE_SUBSCRIBER_ORG_KEY_QUERY, instanceName); 3QueryResult results = conn.query(String.format(METADATA_PACKAGE_VERSION_QUERY, 4subscriberQuery, packageId, major, major, minor, major, minor, patch)); 5 6 return Arrays.stream(results.getRecords()).map(MetadataPackageVersion.class::cast) 7 .filter(mpv -> mpv.getPackageSubscribers() != null) 8 .flatMap(mpv -> Arrays.stream(mpv.getPackageSubscribers().getRecords())) 9 .map(PackageSubscriber.class::cast) 10 .toArray(PackageSubscriber[]::new); 11} - Put it all together. The following code sample shows how to use the previous
methods to modify the workflow to perform package pushes by
instance.
1String[] instances = { "NA4" }; // Here we list the instances we would like to push to 2MetadataPackage metadataPackage = api.getMetadataPackage(); 3MetadataPackageVersion version = api.getLatestMetadataPackageVersion(metadataPackage); 4 5// do pushes by instance to avoid API timeouts retrieving PackageSubscribers 6for (String instanceName : instances) { 7PackageSubscriber[] eligibleSubscribers = api.getEligibleSubscriberIds(version, 8instanceName); 9 10// ... proceed with creating PushRequests and PushJobs as before