Forum Discussion

isxtn's avatar
isxtn
Advisor
8 months ago

Can I cache the JSON returned by an endpoint? Would like to not make the AJAX or API call repeatedly

I have an endpoint that calls an external API which returns JSON.

It's for "related content" for a post. (Yes, I know Khoros has an OOTB and a componentized version of that already for Hermes, but I need to access our own DB of related content, which is reached through an API call.)

My end goal is that each post on our Community have related content from this API but that it only gets called every day or so, and the related content is displayed from the cache. 

Let's just say the JSON is something like this:

 

 

{
 [
   {
     "author":"John",
     "title":"Some article"
     "url":"community/t5/Developer-Discussion/Caching-API-objects/m-p/217953"
   },
   {
     "author":"Mary",
     "title":"Another article"
     "url":"community/t5/Developer-Discussion/dvice-on-performance-for-external-API-query/m-p/208726"
   }
 ]
}

 

 

 

That is currently the output of the endpoint. 

That data is consumed by a component

 

 

<@liaAddScript>
(function($) {
    $(document).ready(function() {
        $.get( "${my_endpoint_url}" ).done(function( data ) {
           console.log(data);

        }).fail(function() {
           console.log('fail');
        }) 
     });
})(LITHIUM.jQuery);
</@liaAddScript>

 

 

(I hate that the only way to get a component is through AJAX, I wish there were a server-side way to get the data. Unless you know another way to get endpoint data...?)

I want to cache the results of the endpoint so that the external API call is not made repeatedly. We want the most efficient execution of this. 

Do I cache it in the endpoint or the component

What's the best practice in order to avoid multiple calls to the API?

Please help a friend out with a code example so I can understand it better. 

I have found several questions about it here on Atlas but they are very old (2015-2018), not answered, or archived, and I'm not sure exactly how to apply it. 

luk is this one still relevant? https://community.khoros.com/t5/Developer-Discussion/Advice-on-performance-for-external-API-query/m-p/208726#M9485


Do you, luk , Claudius or Akenefick DougS  (or anyone else) have some thoughts on this?

Thanks

  • How I resolved this with a little input from here and elsewhere. I have always found the appcache confusing so I needed some help. Thanks.

    <#if page.context?? && page.context.message??>
      <#assign myKey = "myKey_"+page.context.message.uniqueId />
    <#else>
      <#assign myKey = "xyz" />
    </#if>
    <#if appcache.get("myKey", "--EMPTY--") == "--EMPTY--">
      <#assign apiURL = "https://stage.apiurl.com/api/id/A1B2C3d4" />
    
      <#assign apiResponse = http.client.request("https","stage.apiurl.com","/api/id/A1B2C3d4")
      .header("authorization", "APIKey whateveryourA4IK3Yis" )
      .header("content-type", "application/json;charset=UTF-8" )
      </>
    
      <#assign apiResponse = apiResponse.post() />
      <#assign content = apiResponse.content />
      ${appcache.put("myKey", content)}
      ${content} 
    <#else>
      ${appcache.get("myKey")}
    </#if>
  • Doesn't http client request offer caching? Outside of this there are some places you could store this data, like in a custom setting (at the community or node level). 

    HTH

  • How I resolved this with a little input from here and elsewhere. I have always found the appcache confusing so I needed some help. Thanks.

    <#if page.context?? && page.context.message??>
      <#assign myKey = "myKey_"+page.context.message.uniqueId />
    <#else>
      <#assign myKey = "xyz" />
    </#if>
    <#if appcache.get("myKey", "--EMPTY--") == "--EMPTY--">
      <#assign apiURL = "https://stage.apiurl.com/api/id/A1B2C3d4" />
    
      <#assign apiResponse = http.client.request("https","stage.apiurl.com","/api/id/A1B2C3d4")
      .header("authorization", "APIKey whateveryourA4IK3Yis" )
      .header("content-type", "application/json;charset=UTF-8" )
      </>
    
      <#assign apiResponse = apiResponse.post() />
      <#assign content = apiResponse.content />
      ${appcache.put("myKey", content)}
      ${content} 
    <#else>
      ${appcache.get("myKey")}
    </#if>
  • Component caching with liaMarkupCache (khoros.com)

    I'm not very experienced with this, so anyone feel free to expand on this or correct me if I'm wrong. But I don't think this is possible. The ajax call is running in the browser and the caching is happening server side when the Freemarker runs and generates the page.


    isxtn wrote:

     

    (I hate that the only way to get a component is through AJAX, I wish there were a server-side way to get the data. Unless you know another way to get endpoint data...?)


    I think you are right that you would need to be able to get the data server side and I don't think you can call a custom endpoint with Freemarker and you can only call an external API from a custom endpoint. So, I think this is not possible.