org.springframework.scheduling.annotation.Scheduled源码实例Demo

类org.springframework.scheduling.annotation.Scheduled源码实例Demo

下面列出了org.springframework.scheduling.annotation.Scheduled 类实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: mall   文件: OrderJob.java
/**
 * 自动确认订单
 * <p>
 * 定时检查订单未确认情况,如果超时七天则自动确认订单
 * 定时时间是每天凌晨3点。
 * <p>
 * 注意,因为是相隔一天检查,因此导致有订单是超时八天以后才设置自动确认。
 * 这里可以进一步地配合用户订单查询时订单未确认检查,如果订单超时7天则自动确认。
 * 但是,这里可能不是非常必要。相比订单未付款检查中存在商品资源有限所以应该
 * 早点清理未付款情况,这里八天再确认是可以的。。
 */
@Scheduled(cron = "0 0 3 * * ?")
public void checkOrderUnconfirm() {
    logger.info("系统开启任务检查订单是否已经超期自动确认收货");

    List<LitemallOrder> orderList = orderService.queryUnconfirm();
    for (LitemallOrder order : orderList) {
        LocalDateTime ship = order.getShipTime();
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime expired = ship.plusDays(7);
        if (expired.isAfter(now)) {
            continue;
        }

        // 设置订单已取消状态
        order.setOrderStatus(OrderUtil.STATUS_AUTO_CONFIRM);
        order.setConfirmTime(now);
        if (orderService.updateWithOptimisticLocker(order) == 0) {
            logger.info("订单 ID=" + order.getId() + " 数据已经更新,放弃自动确认收货");
        } else {
            logger.info("订单 ID=" + order.getId() + " 已经超期自动确认收货");
        }
    }
}
 
源代码2 项目: ZTuoExchange_framework   文件: OrderUpdateJob.java
@Scheduled(fixedRate = 60*1000)
public void autoCancelOrder(){
    logger.info("start autoCancelOrder...");
    List<ExchangeCoin> coinList = coinService.findAllEnabled();
    coinList.forEach(coin->{
        if(coin.getMaxTradingTime() > 0){
            List<ExchangeOrder> orders =  orderService.findOvertimeOrder(coin.getSymbol(),coin.getMaxTradingTime());
            orders.forEach(order -> {
                // 发送消息至Exchange系统
                kafkaTemplate.send("exchange-order-cancel", JSON.toJSONString(order));
                logger.info("orderId:"+order.getOrderId()+",time:"+order.getTime());
            });
        }
    });
    logger.info("end autoCancelOrder...");
}
 
源代码3 项目: sfg-blog-posts   文件: ApacheHttpClientConfig.java
@Bean
public Runnable idleConnectionMonitor(PoolingHttpClientConnectionManager pool) {
  return new Runnable() {
    @Override
    @Scheduled(fixedDelay = 20000)
    public void run() {
      // only if connection pool is initialised
      if (pool != null) {
        pool.closeExpiredConnections();
        pool.closeIdleConnections(IDLE_CONNECTION_WAIT_TIME, TimeUnit.MILLISECONDS);

        LOG.info("Idle connection monitor: Closing expired and idle connections");
      }
    }
  };
}
 
源代码4 项目: Spring-Boot-Book   文件: CountScheduledTasks.java
@Scheduled(cron = "0 00 2 ? * * ") //每天凌晨2:00执行

    public void syncPostViews() {
        Long startTime = System.nanoTime();
        List dtoList = new ArrayList<>();
        Set<String> keySet = stringRedisTemplate.keys("name::*");
        for (String key : keySet) {
            String views = stringRedisTemplate.opsForValue().get(key);
            String sid = key.replaceAll("name::", "");
            long lid = Long.parseLong(sid);
            long lviews = Long.parseLong(views);
            //批量更新可以用Collection<?>
            articleRepository.updateArticleViewById(lviews, lid);
            //删除key
            stringRedisTemplate.delete(key);
        }

    }
 
源代码5 项目: singleton   文件: SourceRequestCron.java
@Scheduled(fixedDelay = SECOND * 10)
public void syncToInternali18nManager() {
	while (!TaskSysnQueues.SendComponentTasks.isEmpty()) {
		logger.info("begin synch local component Model to VIP i18n");

		RecordModel record = TaskSysnQueues.SendComponentTasks.poll();
		if (record != null) {

			boolean result = singleComponentService.synchComponentFile2I18n(record);

			if (result) {
				singleComponentService.delSourceComponentFile(record);
				logger.info("synch component Model to VIP successfully!!!");
			} else {
				logger.error("synch component Model to VIP failure!!!");
			}

		} else {
			logger.info("no synch component!!!!!");
		}

	}

}
 
源代码6 项目: influx-proxy   文件: HeartBeatService.java
@Scheduled(fixedRate = 5_000)
public void heartBeat() {
    if(proxyConfiguration.isEnable()||StringUtils.isEmpty(opsPath)){
        return;
    }
    try{
        InetUtils.HostInfo hostInfo = inetUtils.findFirstNonLoopbackHostInfo();
        restTemplate.getForObject(opsPath + "/ping?ip={1}&port={2}&managementPort={3}&hostname={4}",
                String.class,
                hostInfo.getIpAddress(),
                port,
                managementPort,
                hostInfo.getHostname());
    }catch (Throwable ignore){
        log.warn("Failed to ping {}",opsPath);
    }
}
 
源代码7 项目: ZTuoExchange_framework   文件: SignJob.java
@Scheduled(cron = "0 0 0 * * ?")
@Transactional(rollbackFor = Exception.class)
public void job() {
    Sign sign = signService.fetchUnderway();
    if (sign == null){
        log.info("sign = { null }");
        return;
    }
    log.info("sign = {}" ,sign);
    memberService.resetSignIn();//赋予签到能力
    //判断今天活动是否到期
    int compare = DateUtil.compare(sign.getEndDate(), new Date());
    log.info("比较时间" );
    log.info("compare = {}" ,compare);
    if (compare != 1) {
        sign.setStatus(SignStatus.FINISH);//当前时间小于等于是结束时间 关闭签到活动
    }
}
 
源代码8 项目: smartapp-sdk-java   文件: StartDayService.java
@Scheduled(cron = "0 0 7 * * *")
public void goodMorning() {
    DevicesApi devicesApi = apiClient.buildClient(DevicesApi.class);
    log.info("waking up");
    installedAppContextStore.get().forEach(context -> {
        log.info("context = " + context);
        ConfigEntries selectedSwitches = context.getInstalledApp().getConfig().get("selectedSwitches");
        for (ConfigEntry entry : selectedSwitches) {
            DeviceConfig deviceConfig = entry.getDeviceConfig();
            if (deviceConfig != null) {
                String auth = context.getAuth();
                devicesApi.executeDeviceCommands(auth, deviceConfig.getDeviceId(), DEVICE_ON);
            }
        }
    });
}
 
源代码9 项目: WeBASE-Front   文件: MonitorService.java
/**
 * scheduled task to sync Monitor Info per 5s
 * 
 * @throws ExecutionException
 * @throws InterruptedException
 */
@Scheduled(cron = "0/5 * * * * ?")
public void syncMonitorInfo() throws ExecutionException, InterruptedException {
    log.debug("begin sync chain data");
    if (!constants.isMonitorEnabled()) {
        return;
    }
    Long currentTime = System.currentTimeMillis();
    // to do add more group
    for (Map.Entry<Integer, Web3j> entry : web3jMap.entrySet()) {
        Monitor monitor = new Monitor();
        CompletableFuture<BlockNumber> blockHeightFuture =
                entry.getValue().getBlockNumber().sendAsync();
        CompletableFuture<PbftView> pbftViewFuture = entry.getValue().getPbftView().sendAsync();
        CompletableFuture<PendingTxSize> pendingTxSizeFuture =
                entry.getValue().getPendingTxSize().sendAsync();

        monitor.setBlockHeight(blockHeightFuture.get().getBlockNumber());
        monitor.setPbftView(pbftViewFuture.get().getPbftView());
        monitor.setPendingTransactionCount(pendingTxSizeFuture.get().getPendingTxSize());
        monitor.setTimestamp(currentTime);
        monitor.setGroupId(entry.getKey());
        monitorRepository.save(monitor);
        log.debug("insert success =  " + monitor.getId());
    }
}
 
源代码10 项目: dts-shop   文件: OrderJob.java
/**
 * 自动确认订单
 * <p>
 * 定时检查订单未确认情况,如果超时七天则自动确认订单 定时时间是每天凌晨3点。
 * <p>
 * 注意,因为是相隔一天检查,因此导致有订单是超时八天以后才设置自动确认。 这里可以进一步地配合用户订单查询时订单未确认检查,如果订单超时7天则自动确认。
 * 但是,这里可能不是非常必要。相比订单未付款检查中存在商品资源有限所以应该 早点清理未付款情况,这里八天再确认是可以的。。
 */
@Scheduled(cron = "0 0 3 * * ?")
public void checkOrderUnconfirm() {
	logger.info("系统开启任务检查订单是否已经超期自动确认收货");

	List<DtsOrder> orderList = orderService.queryUnconfirm();
	for (DtsOrder order : orderList) {
		LocalDateTime ship = order.getShipTime();
		LocalDateTime now = LocalDateTime.now();
		LocalDateTime expired = ship.plusDays(7);
		if (expired.isAfter(now)) {
			continue;
		}

		// 设置订单已取消状态
		order.setOrderStatus(OrderUtil.STATUS_AUTO_CONFIRM);
		order.setConfirmTime(now);
		if (orderService.updateWithOptimisticLocker(order) == 0) {
			logger.info("订单 ID=" + order.getId() + " 数据已经更新,放弃自动确认收货");
		} else {
			logger.info("订单 ID=" + order.getId() + " 已经超期自动确认收货");
		}
	}
}
 
源代码11 项目: dts-shop   文件: OrderJob.java
/**
 * 可评价订单商品超期
 * <p>
 * 定时检查订单商品评价情况,如果确认商品超时七天则取消可评价状态 定时时间是每天凌晨4点。
 */
@Scheduled(cron = "0 0 4 * * ?")
public void checkOrderComment() {
	logger.info("系统开启任务检查订单是否已经超期未评价");

	LocalDateTime now = LocalDateTime.now();
	List<DtsOrder> orderList = orderService.queryComment();
	for (DtsOrder order : orderList) {
		LocalDateTime confirm = order.getConfirmTime();
		LocalDateTime expired = confirm.plusDays(7);
		if (expired.isAfter(now)) {
			continue;
		}

		order.setComments((short) 0);
		orderService.updateWithOptimisticLocker(order);

		List<DtsOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());
		for (DtsOrderGoods orderGoods : orderGoodsList) {
			orderGoods.setComment(-1);
			orderGoodsService.updateById(orderGoods);
		}
	}
}
 
源代码12 项目: dbys   文件: CinemaSocket.java
@Scheduled(cron="0 */1 * * * ?")
public void examine(){
    DELETE_P00L.clear();
    //删除断开的链接
    POOL.forEach((id,e)->{
        if(!e.session.isOpen()){
            POOL.remove(id);
        }
    });
    ROOM_POOL.forEach((id,room)->{
        if(POOL.get(room.getAuthorId())==null){
            if(room.getSockets().size()<2){
                ROOM_POOL.remove(id);
            }else {
                //新房主
                String newId = CinemaSocket.ROOM_POOL.get(id).getSockets().iterator().next();
                //转让
                if (newId != null) {
                    CinemaSocket.ROOM_POOL.get(roomId).setAuthorId(newId);
                }
            }
        }
    });
}
 
源代码13 项目: dts-shop   文件: CouponJob.java
/**
 * 每隔一个小时检查
 */
@Scheduled(fixedDelay = 60 * 60 * 1000)
public void checkCouponExpired() {
	logger.info("系统开启任务检查优惠券是否已经过期");

	List<DtsCoupon> couponList = couponService.queryExpired();
	for (DtsCoupon coupon : couponList) {
		coupon.setStatus(CouponConstant.STATUS_EXPIRED);
		couponService.updateById(coupon);
	}

	List<DtsCouponUser> couponUserList = couponUserService.queryExpired();
	for (DtsCouponUser couponUser : couponUserList) {
		couponUser.setStatus(CouponUserConstant.STATUS_EXPIRED);
		couponUserService.update(couponUser);
	}
}
 
源代码14 项目: mall   文件: CouponJob.java
/**
 * 每隔一个小时检查
 */
@Scheduled(fixedDelay = 60 * 60 * 1000)
public void checkCouponExpired() {
    logger.info("系统开启任务检查优惠券是否已经过期");

    List<LitemallCoupon> couponList = couponService.queryExpired();
    for(LitemallCoupon coupon : couponList){
        coupon.setStatus(CouponConstant.STATUS_EXPIRED);
        couponService.updateById(coupon);
    }

    List<LitemallCouponUser> couponUserList = couponUserService.queryExpired();
    for(LitemallCouponUser couponUser : couponUserList){
        couponUser.setStatus(CouponUserConstant.STATUS_EXPIRED);
        couponUserService.update(couponUser);
    }
}
 
源代码15 项目: cymbal   文件: RedisClusterReplicationCheckJob.java
@Scheduled(cron = "${job.replication.cron}")
public void execute() {
    long startTime = System.currentTimeMillis();
    log.info("RedisClusterReplicationCheckJob started.");
    // TODO: Query with page
    List<ClusterBO> redisClusterBOs = clusterProcessService.queryAllRedisClusters();
    for (ClusterBO eachRedisClusterBO : redisClusterBOs) {
        try {
            if (AlarmLevel.LOG.equals(eachRedisClusterBO.getCluster().getAlarmLevel())) {
                log.warn("Cluster of id '{}' is sign to skip alarm, skip check.",
                        eachRedisClusterBO.getCluster().getClusterId());
                continue;
            }
            doAlarmIfNeeded(eachRedisClusterBO);
        } catch (CymbalException e) {
            log.error(String.format("RedisMasterDistributionCheckJob error of clusterId %s",
                    eachRedisClusterBO.getCluster().getClusterId()), e);
        }
    }

    log.info("RedisClusterReplicationCheckJob finished, duration time {} ms.",
            System.currentTimeMillis() - startTime);
}
 
源代码16 项目: sofa-registry   文件: SyncClientsHeartbeatTask.java
@Scheduled(initialDelayString = "${session.server.syncHeartbeat.fixedDelay}", fixedDelayString = "${session.server.syncHeartbeat.fixedDelay}")
public void syncCounte() {
    long countSub = sessionInterests.count();
    long countPub = sessionDataStore.count();
    long countSubW = sessionWatchers.count();

    int channelCount = 0;
    Server sessionServer = boltExchange.getServer(sessionServerConfig.getServerPort());
    if (sessionServer != null) {
        channelCount = sessionServer.getChannelCount();
    }

    CONSOLE_COUNT_LOGGER.info(
        "Subscriber count: {}, Publisher count: {}, Watcher count: {}, Connection count: {}",
        countSub, countPub, countSubW, channelCount);
}
 
源代码17 项目: youkefu   文件: CleanJobTask.java
@Scheduled(cron= "0 0 1 1 * ?")
   public void task() {
	if(UKDataContext.getContext()!=null && UKDataContext.needRunTask()){
		Page<JobDetail> pageList = null;
		do {
			pageList = jobDetailRepository.findAll(new Specification<JobDetail>(){
				@Override
				public Predicate toPredicate(Root<JobDetail> root, CriteriaQuery<?> query,
						CriteriaBuilder cb) {
					List<Predicate> list = new ArrayList<Predicate>();  

					list.add(cb.equal(root.get("tasktype").as(String.class), UKDataContext.TaskType.RECOVERY.toString()));
					list.add(cb.equal(root.get("taskstatus").as(String.class), UKDataContext.TaskStatusType.NORMAL.getType()));
					//3天前
					list.add(cb.lessThanOrEqualTo(root.get("createtime").as(Date.class), UKTools.getLastDay(3)));
					Predicate[] p = new Predicate[list.size()];  
					return cb.and(list.toArray(p));   
				}}, new PageRequest(0, 1000, Sort.Direction.ASC, new String[] { "createtime" }));
			if(pageList.getContent().size()  > 0 ) {
				jobDetailRepository.delete(pageList.getContent());
			}
		}while(pageList.getContent().size() > 0 );
	}
}
 
@Scheduled(cron="*/30 * * * * ?")
public void extractOutstandingOperationEvents(){
    if(log.isInfoEnabled()){
        log.info("scheduled execution start...");
    }
    
    try{
        operationEventsProcessor.execute();
    }catch(Exception e){
        log.error("operation event processing errors", e);
    }
    
    if(log.isInfoEnabled()){
        log.info("scheduled execution end...");
    }
}
 
源代码19 项目: ZTuoExchange_framework   文件: CoinExchangeRate.java
/**
 * 每小时同步一次价格
 *
 * @throws UnirestException
 */
@Scheduled(cron = "0 0 * * * *")
public void syncPrice() throws UnirestException {
    String url = "https://forex.1forge.com/1.0.2/quotes";
    //如有报错 请自行官网申请获取汇率 或者默认写死
    HttpResponse<JsonNode> resp = Unirest.get(url)
            .queryString("pairs", "USDCNH,USDJPY,USDHKD,SGDCNH")
            .queryString("api_key", "y4lmqQRykolDeO3VkzjYp2XZfgCdo8Tv")
            .asJson();
    log.info("forex result:{}", resp.getBody());
    JSONArray result = JSON.parseArray(resp.getBody().toString());
    result.forEach(json -> {
        JSONObject obj = (JSONObject) json;
        if ("USDCNH".equals(obj.getString("symbol"))) {
            setUsdCnyRate(new BigDecimal(obj.getDouble("price")).setScale(2, RoundingMode.DOWN));
            log.info(obj.toString());
        } else if ("USDJPY".equals(obj.getString("symbol"))) {
            setUsdJpyRate(new BigDecimal(obj.getDouble("price")).setScale(2, RoundingMode.DOWN));
            log.info(obj.toString());
        } else if ("USDHKD".equals(obj.getString("symbol"))) {
            setUsdHkdRate(new BigDecimal(obj.getDouble("price")).setScale(2, RoundingMode.DOWN));
            log.info(obj.toString());
        } else if("SGDCNH".equals(obj.getString("symbol"))){
            setSgdCnyRate(new BigDecimal(obj.getDouble("price")).setScale(2,RoundingMode.DOWN));
            log.info(obj.toString());
        }
    });
}
 
源代码20 项目: ZTuoExchange_framework   文件: CheckExchangeRate.java
@Scheduled(fixedRate = 60 * 1000)
public void syncRate() {
    BigDecimal cnyRate = getUsdCnyRate();
    factory.getCoins().forEach((symbol, value) -> {
        BigDecimal usdRate = getUsdRate(symbol);
        factory.set(symbol, usdRate, cnyRate.multiply(usdRate).setScale(2, RoundingMode.UP));
    });
}
 
源代码21 项目: jhipster-operator   文件: MyApplication.java
@Scheduled(fixedDelay = 10000)
public void reconcileLoop() {
    if (appsOperator.isOn()) {
        if (appsOperator.isInitDone()) {
            logger.info("+ --------------------- RECONCILE LOOP -------------------- + ");
            appsOperator.reconcile();
            logger.info("+ --------------------- END RECONCILE  -------------------- +\n\n\n ");
        } else {
            // Bootstrap
            logger.info("> JHipster Operator Bootstrapping ... ");
            appsOperator.bootstrap();
        }
    }
}
 
源代码22 项目: data-highway   文件: Towtruck.java
@Scheduled(cron = "0 0 * * * *")
void performBackup() throws IOException {
  log.info("Starting backup.");
  try (OutputStream output = outputStreamFactory.apply(keySupplier.get())) {
    mapper.writeValue(output, store);
  }
  log.info("Backup completed.");
}
 
源代码23 项目: spring-boot-examples   文件: LogTimer.java
/**
 * 每隔两分钟启动一次定时器,生成一些日志
 */
@Scheduled(cron = "0 0/2 * * * ?")
public void createLogs() {
    logger.info("本次定时器启动时间:" + new Date().toLocaleString());
    logger.warn("定时器怎么一直在启动呢?");
    logger.debug("尝试关闭一下定时器看看?---实际上并没有编写这个功能");
    logger.error("定时器关闭失败了!!!");
}
 
源代码24 项目: hyena   文件: MemCacheTask.java
@Scheduled(fixedRate = 60 * 1000, initialDelay = 30 * 1000)  // every minutes
public void memCacheTask() {
    //log.debug(">>");
    if (idx % expireRate == 0) {
        pointMemCacheService.expireCache();
    }
    idx++;
}
 
源代码25 项目: seppb   文件: ScheduleMethodHandlerMapping.java
/**
 * 处理@Scheduled标注方法,生成对于的RequestMappingInfo
 * @param method
 * @param handlerType
 * @return
 */
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
    if (method.getAnnotation(Scheduled.class) == null){
        return null;
    }
    return RequestMappingInfo.paths("/schedule/" + handlerType.getSimpleName() + "/" + method.getName())
            .methods(RequestMethod.GET)
            .build();
}
 
源代码26 项目: istio-fleetman   文件: VehicleController.java
@Scheduled(fixedRate=2000)
public void updatePositions()
{
	Collection<VehiclePosition> results = externalService.getAllUpdatedPositionsSince(lastUpdateTime);
	this.lastUpdateTime = new Date();
	for (VehiclePosition next: results)
	{
		this.messagingTemplate.convertAndSend("/vehiclepositions/messages", next);
	}
}
 
源代码27 项目: singleton   文件: SourceSendingCron.java
@Scheduled(cron = "${sync.source.schedule.cron}")
public void syncSourceToRemoteAndLocalInstrument() {
	try {

		LOGGER.debug("!!!!!!!!!!!!!!!!!!!!!!put updated source to instrument queue!!!!!!!!!!!!!!!!!!!!!!");

		instruments.put(SYNCSRC2RMTLCINS);
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		LOGGER.error(e.getMessage(), e);
		Thread.currentThread().interrupt();

	}
}
 
源代码28 项目: seppb   文件: MessageServer.java
/**
 * 默认将内存中维护的websession都推送到客户端
 */
@Override
@Scheduled(fixedRate = 30 * 1000)
public void pushAll() {
	Set<String> users = GlobalCache.getUserSessionMap().keySet();
	users.forEach(this::pushByT);
}
 
源代码29 项目: permission   文件: GoBackTask.java
/**
 * CronTrigger配置完整格式为: [秒][分][小时][日][月][周][年]
 * (cron = "0/2 * * * * ?") //每两秒
 *
 * 每3小时重置mysql和redis
 *
 */
@Scheduled(cron = "0 0 0/3 * * ?")
public void goBack() {
    // 清空缓存
    flushRedis();
    // 重置mysql
    resetDb();
}
 
源代码30 项目: dts-shop   文件: OrderJob.java
/**
 * 自动取消订单
 * <p>
 * 定时检查订单未付款情况,如果超时半个小时则自动取消订单 定时时间是每次相隔半个小时。
 * <p>
 * 注意,因为是相隔半小时检查,因此导致有订单是超时一个小时以后才设置取消状态。 TODO
 * 这里可以进一步地配合用户订单查询时订单未付款检查,如果订单超时半小时则取消。
 */
@Scheduled(fixedDelay = 30 * 60 * 1000)
@Transactional
public void checkOrderUnpaid() {
	logger.info("系统开启任务检查订单是否已经超期自动取消订单");

	List<DtsOrder> orderList = orderService.queryUnpaid();
	for (DtsOrder order : orderList) {
		LocalDateTime add = order.getAddTime();
		LocalDateTime now = LocalDateTime.now();
		LocalDateTime expired = add.plusMinutes(30);
		if (expired.isAfter(now)) {
			continue;
		}

		// 设置订单已取消状态
		order.setOrderStatus(OrderUtil.STATUS_AUTO_CANCEL);
		order.setEndTime(LocalDateTime.now());
		if (orderService.updateWithOptimisticLocker(order) == 0) {
			throw new RuntimeException("更新数据已失效");
		}

		// 商品货品数量增加
		Integer orderId = order.getId();
		List<DtsOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
		for (DtsOrderGoods orderGoods : orderGoodsList) {
			Integer productId = orderGoods.getProductId();
			Short number = orderGoods.getNumber();
			if (productService.addStock(productId, number) == 0) {
				throw new RuntimeException("商品货品库存增加失败");
			}
		}
		logger.info("订单 ID=" + order.getId() + " 已经超期自动取消订单");
	}
}