Product Availability Enrichment
Author:
Fluent Commerce
Changed on:
20 Feb 2024
Key Points
- You would first need to have access to a Fluent account, and have
`localstack`
container running. - There are two possible cache configurations: In-memory cache or External cache.
Prerequisites
Steps
Overview
In this sample project, we will go through some basic features of the Connect SDK by creating a options API that can enrich the response from Fluent Platform.
These are the topics covered by this guide:
- Creating a transformation step
- Define cache configuration to improve the performance of product availability calls
- In-memory cache
- External cache
- Cacheable sample
Prerequisites
- localstack container is running
- You have access to a Fluent account
There is a script `localstack-setup.sh`
bundled with the project that can be used to set up localstack. The script requires some parameters to be configured before it can be executed.
It is best to do the following:
First, run this command to open a session with the localstack container
1docker exec -it localstack /bin/bash
Then use the commands below to create the secrets, but ensure to update the variables: $, $RETAILER, $USERNAME, $PASSWORD and $REGION. Regions values are: sydney, dublin, singapore or north_america.
1docker exec -d localstack awslocal secretsmanager create-secret --name fc/connect/product-availability-enrichment/api/fluent/activeAccounts --secret-string "{\"accounts\":[{\"name\":\"$ACCOUNT\", \"region\":\"$REGION\", \"retailers\":[$RETAILER]}]}" ;
2docker exec -d localstack awslocal secretsmanager create-secret --name fc/connect/product-availability-enrichment/$ACCOUNT/api/fluent-account/$RETAILER --secret-string "{\"retailer\":\"1\", \"userName\":\"$USERNAME\", \"password\":\"$PASSWORD\"}";
3docker exec -d localstack awslocal secretsmanager create-secret --name fc/connect/product-availability-enrichment/$ACCOUNT/api/fluent-account/api-keys --secret-string "{\"api-keys\": [{\"retailer\": \"$RETAILER\",\"username\": \"$USERNAME\",\"password\": \"$PASSWORD\",\"keys\": [{\"key\":\"$API_KEY\",\"expiry\":\"$EXPIRY\"}]}]}";
Use ctrl + D to exit the localstack session.
Define transformation step
By using the anotation `@FulfilmentOptionTransformationStep`
, partners can define multiple transformation step to enrich the fulfilment-option’s response & decide the priority of these steps:

1@Component
2@Slf4j
3@FulfilmentOptionTransformationStep(id = "<transformation-name>", priority = 1)
4public class PickupLocationTransformation implements FulfilmentOptionTransformationChain<FulfilmentRequest, FulfilmentResponse> {
5
6 @Override
7 public FulfilmentResponse transform(final FulfilmentRequest request, final FulfilmentResponse response, final FluentContext context) {
8 //@todo: implement logic here
9 }
10}
Define cache configuration to improve the performance of product availability calls
In-memory cache
The Connect-sdk employs Caffeine-cache as its default cache provider. In addition to the default cache keys of connect-sdk, partners can define their own cache keys with custom configuration. This can be achieved by specifying:
`name`
: cache-names`expiry-in-seconds`
: time-to-live of cache key`max-size`
: capacity of the cache
1 cache:
2 caffeine:
3 - name: location
4 expiry-in-seconds: 300
5 max-size: 10000
External cache
If partners want to integrate with the other kinds of Cache Providers please refer to Spring-cache solution: IO
For example, to define a new Cache Manager using Redis Cache:
1public class RedisCacheConfiguration {
2
3 public static final String CUSTOM_CACHE_MANAGER = "custom-cache-manager";
4 public static final String LOCATION_CACHE = "location";
5
6 @Value("${fluent-connect.fulfilment-option.location-cache-ttl-seconds:300}")
7 private Duration LOCATION_TTL_SECONDS = 300;
8
9 @Bean
10 @Primary
11 public CacheManager cacheManager(RedisTemplate<String, Object> template) {
12 RedisCacheManager redisCacheManager =
13 RedisCacheManager.RedisCacheManagerBuilder
14 .fromConnectionFactory(template.getConnectionFactory())
15 .cacheDefaults(getCacheConfigurationWithTtl(template, duration))
16 .withCacheConfiguration(LOCATION_CACHE, getCacheConfigurationWithTtl(template, LOCATION_TTL_SECONDS))
17// .withCacheConfiguration("other-cache", getCacheConfigurationWithTtl(template, secondDuration))
18 .transactionAware()
19 .build();
20 return redisCacheManager;
21 }
22
23 private RedisCacheConfiguration getCacheConfigurationWithTtl(
24 RedisTemplate<String, Object> template, Duration duration) {
25
26 return RedisCacheConfiguration
27 .defaultCacheConfig()
28 .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(
29 template.getStringSerializer()))
30 .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(
31 template.getValueSerializer()))
32 .disableCachingNullValues()
33 .entryTtl(duration);
34 }
35
36}
Cacheable sample:
1public class LocationService {
2
3 @Cacheable(cacheManager = SDK_CACHE_MANAGER, cacheNames = LOCATION_CACHE, key = "#ref")
4 //@Cacheable(cacheManager = CUSTOM_CACHE_MANAGER, cacheNames = LOCATION_CACHE, key = "#ref")
5 public Optional<GetLocationQuery.Location> getLocation(@NotNull final FluentContext context, @NotNull final String ref) {
6 final GetLocationQuery query = GetLocationQuery.builder().ref(ref).build();
7 final GetLocationQuery.Data locationData = context.executeQuery(query, GetLocationQuery.Data.class);
8 if (locationData != null) {
9 return Optional.ofNullable(locationData.location());
10 }
11 return Optional.empty();
12 }
13
14}
Get Fulfilment Option
Beside default fulfilment-options’s response, there are 2 extra attributes: pickupLocationAddress & pickupLocationOpeningTime

1curl --location --request POST 'http://localhost:8080/api/v1/fluent-connect/fulfilment-option' \
2--header 'Authorization: ApiKey 1234567890123456' \
3--header 'fluent.account: CNCTDEV' \
4--header 'Content-Type: application/json' \
5--header 'Cookie: JSESSIONID=B1AD8588367D0E2BD9E63340119E2B46' \
6--data-raw '{
7 "ref": "9c546d29-89a8-48b4-8d6b-fd7b0e2a2497",
8 "retailerId": "67",
9 "type": "CC",
10 "orderType": "CC",
11 "address": {
12 "longitude": 144.969574,
13 "latitude": -37.812104
14 },
15 "products": [
16 {
17 "requestedQuantity": 1,
18 "productRef": "P041122174751_1",
19 "catalogueRef": "PC:MASTER:67"
20 }
21 ]
22}