code: func (l *Link) RetryableRPC(ctx context.Context, times int, delay time.Duration, msg *amqp.Message) (*Response, error) {
  	span, ctx := tracing.StartSpanFromContext(ctx, "az-amqp-common.rpc.RetryableRPC")
  	defer span.End()
  
  	res, err := common.Retry(times, delay, func() (interface{}, error) {
  		span, ctx := tracing.StartSpanFromContext(ctx, "az-amqp-common.rpc.RetryableRPC.retry")
  		defer span.End()
  
  		res, err := l.RPC(ctx, msg)
  		if err != nil {
  			log.For(ctx).Error(fmt.Errorf("error in RPC via link %s: %v", l.id, err))
  			return nil, err
  		}
  
  		switch {
  		case res.Code >= 200 && res.Code < 300:
  			log.For(ctx).Debug(fmt.Sprintf("successful rpc on link %s: status code %d and description: %s", l.id, res.Code, res.Description))
  			return res, nil
  		case res.Code >= 500:
  			errMessage := fmt.Sprintf("server error link %s: status code %d and description: %s", l.id, res.Code, res.Description)
  			log.For(ctx).Error(errors.New(errMessage))
  			return nil, common.Retryable(errMessage)
  		default:
  			errMessage := fmt.Sprintf("unhandled error link %s: status code %d and description: %s", l.id, res.Code, res.Description)
  			log.For(ctx).Error(errors.New(errMessage))
  			return nil, common.Retryable(errMessage)
  		}
  	})
  	if err != nil {
  		return nil, err
  	}
  	return res.(*Response), nil
  }
docs: // RetryableRPC attempts to retry a request a number of times with delay