@Override
    public List<HivePartitionName> refreshTableBackground(String hiveDbName, String hiveTblName, boolean onlyCachedPartitions) {
        DatabaseTableName databaseTableName = DatabaseTableName.of(hiveDbName, hiveTblName);
        if (lastAccessTimeMap.containsKey(databaseTableName)) {
            long lastAccessTime = lastAccessTimeMap.get(databaseTableName);
            long intervalSec = (System.currentTimeMillis() - lastAccessTime) / 1000;
            long refreshIntervalSinceLastAccess = Config.background_refresh_metadata_time_secs_since_last_access_secs;
            if (refreshIntervalSinceLastAccess >= 0 && intervalSec > refreshIntervalSinceLastAccess) {
                // invalidate table cache
                invalidateTable(hiveDbName, hiveTblName);
                lastAccessTimeMap.remove(databaseTableName);
                LOG.info("{}.{} skip refresh because of the last access time is {}", hiveDbName, hiveTblName,
                        LocalDateTime.ofInstant(Instant.ofEpochMilli(lastAccessTime), ZoneId.systemDefault()));
                return null;
            }
        }

        List<HivePartitionName> refreshPartitionNames = refreshTable(hiveDbName, hiveTblName, onlyCachedPartitions);
        Set<DatabaseTableName> cachedTableNames = getCachedTableNames();
        lastAccessTimeMap.keySet().removeIf(tableName -> !(cachedTableNames.contains(tableName)));
        LOG.info("Refresh table {}.{} in background", hiveDbName, hiveTblName);
        return refreshPartitionNames;
    }
@Test
    public void testRefreshTableBackground() throws InterruptedException {
        CachingHiveMetastore cachingHiveMetastore = new CachingHiveMetastore(
                metastore, executor, expireAfterWriteSec, refreshAfterWriteSec, 1000, false);
        Assert.assertFalse(cachingHiveMetastore.tableNameLockMap.containsKey(
                DatabaseTableName.of("db1", "tbl1")));
        try {
            // mock query table tbl1
            List<String> partitionNames = cachingHiveMetastore.getPartitionKeysByValue("db1", "tbl1",
                    HivePartitionValue.ALL_PARTITION_VALUES);
            cachingHiveMetastore.getPartitionsByNames("db1",
                    "tbl1", partitionNames);
            // put table tbl1 in table cache
            cachingHiveMetastore.refreshTable("db1", "tbl1", true);
        } catch (Exception e) {
            Assert.fail();
        }
        Assert.assertTrue(cachingHiveMetastore.isTablePresent(DatabaseTableName.of("db1", "tbl1")));

        try {
            cachingHiveMetastore.refreshTableBackground("db1", "tbl1", true);
        } catch (Exception e) {
            Assert.fail();
        }
        // not skip refresh table, table cache still exist
        Assert.assertTrue(cachingHiveMetastore.isTablePresent(DatabaseTableName.of("db1", "tbl1")));
        // sleep 1s, background refresh table will be skipped
        Thread.sleep(1000);
        long oldValue = Config.background_refresh_metadata_time_secs_since_last_access_secs;
        // not refresh table, just skip refresh table
        Config.background_refresh_metadata_time_secs_since_last_access_secs = 0;

        try {
            cachingHiveMetastore.refreshTableBackground("db1", "tbl1", true);
        } catch (Exception e) {
            Assert.fail();
        } finally {
            Config.background_refresh_metadata_time_secs_since_last_access_secs = oldValue;
        }
        // table cache will be removed because of skip refresh table
        Assert.assertFalse(cachingHiveMetastore.isTablePresent(DatabaseTableName.of("db1", "tbl1")));
    }