private Record valueForObject(Record record, ResponseField field) { CacheReference cacheReference; CacheKey fieldCacheKey = cacheKeyResolver.fromFieldArguments(field, variables); if (!fieldCacheKey.equals(CacheKey.NO_KEY)) { cacheReference = new CacheReference(fieldCacheKey.key()); } else { cacheReference = fieldValue(record, field); } if (cacheReference != null) { Record referencedRecord = readableCache.read(cacheReference.key(), cacheHeaders); if (referencedRecord == null) { // we are unable to find record in the cache by reference, // means it was removed intentionally by using imperative store API or // evicted from LRU cache, we must prevent of further resolving cache response as it's broken throw new IllegalStateException("Cache MISS: failed to find record in cache by reference"); } return referencedRecord; } return null; }
@Override public Object nextScalar(boolean optional) throws IOException { Object scalar = super.nextScalar(optional); if (scalar instanceof String) { String scalarString = (String) scalar; if (CacheReference.canDeserialize(scalarString)) { return CacheReference.deserialize(scalarString); } } return scalar; }
jsonWriter.value((Number) value); } else if (value instanceof CacheReference) { jsonWriter.value(((CacheReference) value).serialize()); } else if (value instanceof List) { jsonWriter.beginArray();
public static CacheReference deserialize(String serializedCacheReference) { Matcher matcher = SERIALIZATION_REGEX_PATTERN.matcher(serializedCacheReference); if (!matcher.find() || matcher.groupCount() != 1) { throw new IllegalArgumentException("Not a cache reference: " + serializedCacheReference + " Must be of the form:" + SERIALIZATION_TEMPLATE); } return new CacheReference(matcher.group(1)); }
private static int weighField(Object field) { if (field instanceof List) { int size = SIZE_OF_ARRAY_OVERHEAD; for (Object listItem : (List) field) { size += weighField(listItem); } return size; } if (field instanceof String) { return ((String) field).getBytes(Charset.defaultCharset()).length; } else if (field instanceof Boolean) { return SIZE_OF_BOOLEAN; } else if (field instanceof BigDecimal) { return SIZE_OF_BIG_DECIMAL; } else if (field instanceof CacheReference) { return SIZE_OF_CACHE_REFERENCE_OVERHEAD + ((CacheReference) field).key().getBytes(Charset.defaultCharset()).length; } else if (field == null) { return SIZE_OF_NULL; } throw new IllegalStateException("Unknown field type in Record. " + field.getClass().getName()); }
@Override public void didResolveObject(ResponseField field, Optional<R> objectSource) { path = pathStack.pop(); if (objectSource.isPresent()) { Record completedRecord = currentRecordBuilder.build(); valueStack.push(new CacheReference(completedRecord.key())); dependentKeys.add(completedRecord.key()); recordSet.merge(completedRecord); } currentRecordBuilder = recordStack.pop().toBuilder(); }
@SuppressWarnings("unchecked") private List valueForList(List values) { if (values == null) { return null; } List result = new ArrayList(); for (Object value : values) { if (value instanceof CacheReference) { CacheReference reference = (CacheReference) value; Record referencedRecord = readableCache.read(reference.key(), cacheHeaders); if (referencedRecord == null) { // we are unable to find record in the cache by reference, // means it was removed intentionally by using imperative store API or // evicted from LRU cache, we must prevent of further resolving cache response as it's broken throw new IllegalStateException("Cache MISS: failed to find record in cache by reference"); } result.add(referencedRecord); } else if (value instanceof List) { result.add(valueForList((List) value)); } else { result.add(value); } } return result; }
private Record valueForObject(Record record, ResponseField field) { CacheReference cacheReference; CacheKey fieldCacheKey = cacheKeyResolver.fromFieldArguments(field, variables); if (fieldCacheKey != CacheKey.NO_KEY) { cacheReference = new CacheReference(fieldCacheKey.key()); } else { cacheReference = fieldValue(record, field); } if (cacheReference != null) { Record referencedRecord = readableCache.read(cacheReference.key(), cacheHeaders); if (referencedRecord == null) { // we are unable to find record in the cache by reference, // means it was removed intentionally by using imperative store API or // evicted from LRU cache, we must prevent of further resolving cache response as it's broken throw new IllegalStateException("Cache MISS: failed to find record in cache by reference"); } return referencedRecord; } return null; }
@Test public void testRecordWeigher() { Record.Builder recordBuilder = Record.builder("root"); BigDecimal expectedBigDecimal = new BigDecimal(1.23); String expectedStringValue = "StringValue"; Boolean expectedBooleanValue = true; CacheReference expectedCacheReference = new CacheReference("foo"); List<CacheReference> expectedCacheReferenceList = Arrays.asList(new CacheReference("bar"), new CacheReference ("baz")); List<Object> expectedScalarList = Arrays.<Object>asList("scalarOne", "scalarTwo"); recordBuilder.addField("bigDecimal", expectedBigDecimal); recordBuilder.addField("string", expectedStringValue); recordBuilder.addField("boolean", expectedBooleanValue); recordBuilder.addField("cacheReference", expectedCacheReference); recordBuilder.addField("scalarList", expectedScalarList); recordBuilder.addField("referenceList", expectedCacheReferenceList); Record record = recordBuilder.build(); record.sizeEstimateBytes(); //It's difficult to say what the "right" size estimate is, so just checking it is has been calculate at all. assertThat(record.sizeEstimateBytes()).isNotEqualTo(-1); } }
@Override public Object nextScalar(boolean optional) throws IOException { Object scalar = super.nextScalar(optional); if (scalar instanceof String) { String scalarString = (String) scalar; if (CacheReference.canDeserialize(scalarString)) { return CacheReference.deserialize(scalarString); } } return scalar; }
@Override public boolean remove(@NotNull final CacheKey cacheKey, final boolean cascade) { checkNotNull(cacheKey, "cacheKey == null"); boolean result = nextCache().map(new Function<NormalizedCache, Boolean>() { @NotNull @Override public Boolean apply(@NotNull NormalizedCache cache) { return cache.remove(cacheKey, cascade); } }).or(Boolean.FALSE); RecordJournal recordJournal = lruCache.getIfPresent(cacheKey.key()); if (recordJournal != null) { lruCache.invalidate(cacheKey.key()); result = true; if (cascade) { for (CacheReference cacheReference : recordJournal.snapshot.referencedFields()) { result = result & remove(CacheKey.from(cacheReference.key()), true); } } } return result; }
private static void writeJsonValue(Object value, JsonWriter jsonWriter) throws IOException { if (value == null) { jsonWriter.nullValue(); } else if (value instanceof String) { jsonWriter.value((String) value); } else if (value instanceof Boolean) { jsonWriter.value((boolean) value); } else if (value instanceof Number) { jsonWriter.value((Number) value); } else if (value instanceof CacheReference) { jsonWriter.value(((CacheReference) value).serialize()); } else if (value instanceof List) { jsonWriter.beginArray(); for (Object item : (List) value) { writeJsonValue(item, jsonWriter); } jsonWriter.endArray(); } else { throw new RuntimeException("Unsupported record value type: " + value.getClass()); } } }
private Record valueForObject(Record record, ResponseField field) { CacheReference cacheReference; CacheKey fieldCacheKey = cacheKeyResolver.fromFieldArguments(field, variables); if (fieldCacheKey != CacheKey.NO_KEY) { cacheReference = new CacheReference(fieldCacheKey.key()); } else { cacheReference = fieldValue(record, field); } if (cacheReference != null) { Record referencedRecord = readableCache.read(cacheReference.key(), cacheHeaders); if (referencedRecord == null) { // we are unable to find record in the cache by reference, // means it was removed intentionally by using imperative store API or // evicted from LRU cache, we must prevent of further resolving cache response as it's broken throw new IllegalStateException("Cache MISS: failed to find record in cache by reference"); } return referencedRecord; } return null; }
String expectedStringValue = "StringValue"; Boolean expectedBooleanValue = true; CacheReference expectedCacheReference = new CacheReference("foo"); List<CacheReference> expectedCacheReferenceList = Arrays.asList(new CacheReference("bar"), new CacheReference("baz")); List<Object> expectedScalarList = Arrays.<Object>asList("scalarOne", "scalarTwo"); List<List<String>> expectedListOfScalarList = Arrays.asList(Arrays.asList("scalarOne", "scalarTwo"));
@Override public Object nextScalar(boolean optional) throws IOException { Object scalar = super.nextScalar(optional); if (scalar instanceof String) { String scalarString = (String) scalar; if (CacheReference.canDeserialize(scalarString)) { return CacheReference.deserialize(scalarString); } } return scalar; }
@Override public boolean remove(@NotNull final CacheKey cacheKey, final boolean cascade) { checkNotNull(cacheKey, "cacheKey == null"); boolean result; result = nextCache().map(new Function<NormalizedCache, Boolean>() { @NotNull @Override public Boolean apply(@NotNull NormalizedCache cache) { return cache.remove(cacheKey, cascade); } }).or(Boolean.FALSE); Record record = lruCache.getIfPresent(cacheKey.key()); if (record != null) { lruCache.invalidate(cacheKey.key()); result = true; if (cascade) { for (CacheReference cacheReference : record.referencedFields()) { result = result & remove(CacheKey.from(cacheReference.key()), true); } } } return result; }
private static void writeJsonValue(Object value, JsonWriter jsonWriter) throws IOException { if (value == null) { jsonWriter.nullValue(); } else if (value instanceof String) { jsonWriter.value((String) value); } else if (value instanceof Boolean) { jsonWriter.value((boolean) value); } else if (value instanceof Number) { jsonWriter.value((Number) value); } else if (value instanceof CacheReference) { jsonWriter.value(((CacheReference) value).serialize()); } else if (value instanceof List) { jsonWriter.beginArray(); for (Object item : (List) value) { writeJsonValue(item, jsonWriter); } jsonWriter.endArray(); } else { throw new RuntimeException("Unsupported record value type: " + value.getClass()); } } }
public static CacheReference deserialize(String serializedCacheReference) { Matcher matcher = SERIALIZATION_REGEX_PATTERN.matcher(serializedCacheReference); if (!matcher.find() || matcher.groupCount() != 1) { throw new IllegalArgumentException("Not a cache reference: " + serializedCacheReference + " Must be of the form:" + SERIALIZATION_TEMPLATE); } return new CacheReference(matcher.group(1)); }
private static int weighField(Object field) { if (field instanceof List) { int size = SIZE_OF_ARRAY_OVERHEAD; for (Object listItem : (List) field) { size += weighField(listItem); } return size; } if (field instanceof String) { return ((String) field).getBytes().length; } else if (field instanceof Boolean) { return SIZE_OF_BOOLEAN; } else if (field instanceof BigDecimal) { return SIZE_OF_BIG_DECIMAL; } else if (field instanceof CacheReference) { return SIZE_OF_CACHE_REFERENCE_OVERHEAD + ((CacheReference) field).key().getBytes().length; } else if (field == null) { return SIZE_OF_NULL; } throw new IllegalStateException("Unknown field type in Record. " + field.getClass().getName()); }
public static CacheReference deserialize(String serializedCacheReference) { Matcher matcher = SERIALIZATION_REGEX_PATTERN.matcher(serializedCacheReference); if (!matcher.find() || matcher.groupCount() != 1) { throw new IllegalArgumentException("Not a cache reference: " + serializedCacheReference + " Must be of the form:" + SERIALIZATION_TEMPLATE); } return new CacheReference(matcher.group(1)); }