code: func (c *Connector) Range(ctx context.Context, ei *dosa.EntityInfo, columnConditions map[string][]*dosa.Condition, minimumFields []string, token string, limit int) ([]map[string]dosa.FieldValue, string, error) {
  	sourceRows, sourceToken, sourceErr := c.Next.Range(ctx, ei, columnConditions, dosa.All(), token, limit)
  	if !c.isCacheable(ei) || dosa.ErrorIsNotFound(sourceErr) {
  		return sourceRows, sourceToken, sourceErr
  	}
  	cacheKey := rangeQuery{
  		Conditions: dosa.NormalizeConditions(columnConditions),
  		Token:      token,
  		Limit:      limit,
  	}
  	rangeResult := rangeResults{
  		TokenNext: sourceToken,
  		Rows:      sourceRows,
  	}
  
  	if sourceErr == nil {
  		w := func() error {
  			return c.writeKeyValueToFallback(ctx, ei, cacheKey, rangeResult)
  		}
  		_ = c.cacheWrite(w)
  
  		return sourceRows, sourceToken, sourceErr
  	}
  
  	value, err := c.getValueFromFallback(ctx, ei, cacheKey)
  	c.logFallback("RANGE", ei.Def.Name, err)
  	if err != nil {
  		return sourceRows, sourceToken, sourceErr
  	}
  	unpack := rangeResults{}
  	err = c.encoder.Decode(value, &unpack)
  	if err != nil {
  		return sourceRows, sourceToken, sourceErr
  	}
  
  	return rawRowsAsPointers(ei, unpack.Rows), unpack.TokenNext, err
  }
docs: // Range returns range from origin, reverts to fallback if origin fails