Skip to content

Commit

Permalink
Persistent Cache Timestamp API
Browse files Browse the repository at this point in the history
- New endpoint
    - For every table that has endpoints that are being persistently
    cached the endpoint returns a table name timestamp pair of the
    last time the table was updated
    - If the table has never been updated, it instead returns
    the creation date of the table
- This feature requires SQL 5.7.2+ because the InnoDb engine did not
update this column correctly before then
    - updated the requirements in the docs to require 5.7 rather than 5.x
  • Loading branch information
Luke-Sikina committed Nov 11, 2019
1 parent 6d6ff98 commit f5211d8
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 2 deletions.
4 changes: 3 additions & 1 deletion docs/Deploy-Using-Docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ docker network create "cbio-net"

## 2. Database Setup

As of this writing, the cBioPortal software runs properly on MySQL version 5.0.x. The software can be found and downloaded from the [MySQL website](https://www.mysql.com).
The cBioPortal software should run properly on MySQL version 5.7.x. Versions higher than 5.7.x can cause an issue
while loading the database schema. Minor versions lower than 5.7.x will cause issues with persistent cache invalidation.
The software can be found and downloaded from the [MySQL website](http://www.mysql.com/).

There are two options to set up the cBioPortal Database:
2.1 Run MySQL on the host.
Expand Down
3 changes: 2 additions & 1 deletion docs/Software-Requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ This page describes various system software required to run the cBioPortal.

## MySQL

The cBioPortal software should run properly on MySQL version 5.x.x; to avoid a known issue while loading the database schema, 5.7.x or lower is recommended.
The cBioPortal software should run properly on MySQL version 5.7.x. Versions higher than 5.7.x can cause an issue
while loading the database schema. Minor versions lower than 5.7.x will cause issues with persistent cache invalidation.
The software can be found and downloaded from the [MySQL website](http://www.mysql.com/).

On Ubuntu: ```sudo apt-get install mysql-server```
Expand Down
26 changes: 26 additions & 0 deletions model/src/main/java/org/cbioportal/model/TableTimestampPair.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.cbioportal.model;

import javax.validation.constraints.NotNull;
import java.io.Serializable;

public class TableTimestampPair implements Serializable {
@NotNull
private String tableName;
private String updateTime;

public String getUpdateTime() {
return updateTime;
}

public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}

public String getTableName() {
return tableName;
}

public void setTableName(String tableName) {
this.tableName = tableName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.cbioportal.persistence;

import org.cbioportal.model.TableTimestampPair;

import java.util.Date;
import java.util.List;

public interface StaticDataTimeStampRepository {
List<TableTimestampPair> getTimestamps(List<String> tables);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.cbioportal.persistence.mybatis;

import org.cbioportal.model.TableTimestampPair;
import org.cbioportal.persistence.StaticDataTimeStampRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public class StaticDataTimeStampMyBatisRepository implements StaticDataTimeStampRepository {

@Autowired
private StaticDataTimestampMapper staticDataTimestampMapper;

@Override
public List<TableTimestampPair> getTimestamps(List<String> tableNames) {
return staticDataTimestampMapper.getTimestamps(tableNames);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.cbioportal.persistence.mybatis;

import org.cbioportal.model.TableTimestampPair;

import java.util.List;

public interface StaticDataTimestampMapper {
List<TableTimestampPair> getTimestamps(List<String> tables);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.cbioportal.persistence.mybatis.StaticDataTimestampMapper">
<select id="getTimestamps" resultType="org.cbioportal.model.TableTimestampPair">
SELECT
TABLE_NAME AS tableName,
COALESCE(UPDATE_TIME, CREATE_TIME) AS updateTime
FROM information_schema.tables
WHERE
TABLE_SCHEMA='cbioportal'
<if test="list != null and !list.isEmpty()">
AND TABLE_NAME IN
<foreach item="item" collection="list" open="(" separator="," close=");">
#{item}
</foreach>
</if>
</select>
</mapper>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.cbioportal.service;

import org.cbioportal.model.TableTimestampPair;

import java.util.Date;
import java.util.List;

public interface StaticDataTimestampService {
List<TableTimestampPair> getTimestamps(List<String> tables);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.cbioportal.service.impl;

import org.cbioportal.model.TableTimestampPair;
import org.cbioportal.service.StaticDataTimestampService;
import org.cbioportal.persistence.StaticDataTimeStampRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class StaticDataTimestampServiceImpl implements StaticDataTimestampService {
@Autowired
private StaticDataTimeStampRepository staticDataTimeStampRepository;

@Override
public List<TableTimestampPair> getTimestamps(List<String> tables) {
return staticDataTimeStampRepository.getTimestamps(tables);
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.cbioportal.service.impl;

import org.cbioportal.model.TableTimestampPair;
import org.cbioportal.persistence.StaticDataTimeStampRepository;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.Collections;

@RunWith(MockitoJUnitRunner.class)
public class StaticDataTimestampServiceImplTest extends BaseServiceImplTest {
@InjectMocks
private StaticDataTimestampServiceImpl infoService;

@Mock
private StaticDataTimeStampRepository repository;

@Test
public void TestGetTimestamps() {
TableTimestampPair pair = new TableTimestampPair();
pair.setTableName("gene");
pair.setUpdateTime("2019-11-11 08:41:15");

Mockito.when(repository.getTimestamps(Mockito.anyList())).thenReturn(
Collections.singletonList(pair));

Assert.assertEquals(
repository.getTimestamps(Collections.singletonList("gene")),
Collections.singletonList(pair));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.cbioportal.web;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.cbioportal.model.TableTimestampPair;
import org.cbioportal.service.StaticDataTimestampService;
import org.cbioportal.web.config.annotation.InternalApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.List;

@InternalApi
@RestController
@Validated
@Api(tags = "Timestamps", description = " ")
public class StaticDataTimestampController {
private static final List<String> tables = Collections.singletonList("gene");
@Autowired
private StaticDataTimestampService service;

@RequestMapping(value = "/timestamps", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation("Get the last time each static resouce was updated")
public ResponseEntity<List<TableTimestampPair>> getAllTimestamps() {
return new ResponseEntity<>(service.getTimestamps(tables), HttpStatus.OK);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.cbioportal.web;

import org.cbioportal.model.TableTimestampPair;
import org.cbioportal.service.StaticDataTimestampService;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import java.util.Collections;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("/applicationContext-web-test.xml")
@Configuration
public class StaticDataTimestampControllerTest {
@Autowired
private WebApplicationContext wac;

@Autowired
private StaticDataTimestampService service;

private MockMvc mockMvc;

@Bean
public StaticDataTimestampService staticDataTimestampService() {
return Mockito.mock(StaticDataTimestampService.class);
}

@Before
public void setUp() throws Exception {
Mockito.reset(service);
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}

@Test
public void getAllTimestamps() throws Exception {
TableTimestampPair pair = new TableTimestampPair();
pair.setUpdateTime("1997-08-13 22:00:00");
pair.setTableName("gene");
Mockito.when(service.getTimestamps(Mockito.anyList())).thenReturn(Collections.singletonList(pair));

mockMvc.perform(MockMvcRequestBuilders.get("/timestamps")
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(1)))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].tableName").value("gene"))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].updateTime").value("1997-08-13 22:00:00"));
}
}

0 comments on commit f5211d8

Please sign in to comment.