Search code examples
azure-service-fabric

Determine partition key (name or number range) from partition ID


For a stateful service, is there a way a replica can determine from its partition ID (a GUID value) the partition key (string or number/number range)? Looking at the .NET API, it's only possible to get replica ID from a ServicePartitionKey, but not the other way around.


Solution

  • No, there is no way you can get it directly from the partition id (guid). Depending on which partitioning kind (Singleton, Int64Range or Named) you use and how that is setup it might be possible to derive it, but there is no way to do it directly from the service.

    It makes sense that it is this way, consider a scenario where you have a service with an Int64 partitioning scheme with low key = 0 and high key = 9 and 2 partitions. Any partition key from 0 to 4 would end up on partition no. 1 and keys 5 - 9 on partition no. 2. But since any call with a key from 0 to 4 would end up on the same instance of that service then the key would really be per call, not per service, so from the service's point of view, how would it know which key it's partition corresponds to, unless that was something baked into the client's call to the service and you could say "for this call to partition XXX the key is 123". Currently there is no such information baked into fabric transport communication, the partition is resolved on the client side and never passed to the service.

    What you could do is figure out the range a partition id is in. For a Singleton partition scheme, well you are on 'the partition', not much more to discuss there. For Named and Int64 you can enumerate the partitions using FabricClient.QueryManager:

    var fabricClient = new FabricClient();
    var partitionList = await fabricClient.QueryManager.GetPartitionListAsync(serviceName);
    
    foreach (var partition in partitionList)
    {
        // Partition Guid
        var partitionId = partition.PartitionInformation.Id;
    
        // Int 64 Range
        var int64PartitionInfo = partition.PartitionInformation as Int64RangePartitionInformation;
        var lowKey = int64PartitionInfo?.LowKey;
        var highKey = int64PartitionInfo?.HighKey;
    
        // Named Range
        var namedPartitionInfo = partition.PartitionInformation as NamedPartitionInformation;
        var name = namedPartitionInfo.Name;
    }
    

    For Named range if actually does give you the partition key since it's a one-to-one mapping there, but for Int64 range you will only get the span of ints for that partition.

    The above code is also something you probably don't want to run every time you want to look for a partition key as the FabricClient.QueryManager is relatively slow.

    The other option you have, if it is important for you to be able to know the partition key in each service call is to simply add it as a message parameter or a message header in your calls to the client (similar to this Passing user and auditing information in calls to Reliable Services in Service Fabric transport)