package com.jackson.task.timer;
import com.jackson.bean.ContextSrc;
import com.jackson.common.control.ProxyController;
import com.jackson.common.source.CommonSource;
import com.jackson.db.po.Proxy;
import com.jackson.db.po.Url;
import com.jackson.db.service.UrlService;
import com.jackson.reservoir.TimedUrlPool;
import com.jackson.task.RequestParserTask;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Created by Jackson on 2016/12/27.
* 用来做定时请求的task
*/
public class TimedTask extends RequestParserTask {
private final TimedUrlPool timedUrlPool;
private final TimedUrlPool.TimedUrl timedUrl;
private final ProxyController proxyController;
private Proxy proxy;
private final CommonSource source;
private static Logger logger = LogManager.getLogger(TimedTask.class.getName());
public TimedTask(TimedUrlPool.TimedUrl timedUrl, TimedUrlPool timedUrlPool,CommonSource source) {
this(timedUrl,timedUrlPool,null,null,source);
}
public TimedTask(TimedUrlPool.TimedUrl timedUrl, TimedUrlPool timedUrlPool, ProxyController proxyController,Proxy proxy,CommonSource source) {
this.timedUrl = timedUrl;
this.timedUrlPool = timedUrlPool;
this.proxyController = proxyController;
this.proxy = proxy;
this.source = source;
}
@Override
public HttpRequestBase getHttpRequest() {
return source.pollHttpGet(getUrl());
}
@Override
protected Url getUrl() {
return timedUrl.getUrl();
}
@Override
protected Proxy getProxy() {
return proxy;
}
@Override
protected ProxyController getProxyController() {
return proxyController;
}
@Override
protected UrlService getUrlService() {
return null;
}
@Override
protected boolean onStatusCode(int statusCode, CloseableHttpResponse response) {
if(!(statusCode >= 200 && statusCode<300)){
logger.error("请求失败 statusCode:{}", statusCode,response);
}
return statusCode >= 200 && statusCode<300;
}
@Override
public void onRequestException(Exception e, Url url, HttpRequestBase httpRequest) {
logger.error("请求异常 url:{} Exception:{}", url.getUrl(),e.toString());
}
@Override
public void onRequestFinish(boolean isRequestOk, CloseableHttpClient httpClient, HttpRequestBase httpRequest, Url url) {
if (!isRequestOk) {
//timedUrlPool.offer(timedUrl);//如果失败,就重新放入,等着下次接着用,如果成功等着解析,解析成功后回收
addImmediateTask(getUrl(),0);
}
if(url.getRequestState() == Url.REQUEST_STATE_GET){
source.offerHttpGet((HttpGet) httpRequest);
}
if(url.getRequestState() == Url.REQUEST_STATE_POST){
source.offerHttpPost((HttpPost) httpRequest);
}
}
@Override
protected ContextSrc getContextSrc() {
return null;
}
@Override
protected void onParseException(Exception e, Url url, String content) {
logger.error("解析异常 url:{},Exception{},content:{}", url.getUrl(),e.toString(), content);//记录错误日志,方便排查问题,改解析代码
}
@Override
protected void onParseFinish(boolean parseSuccess, Url url, String content) {
//解析失败一次,proxy 就放弃使用
if (parseSuccess){
url.setParserFailureTime(0);
if(proxy!=null){
proxyController.getProxyPool().offer(proxy);
}
timedUrlPool.offer(timedUrl);
}
else {
url.setParserFailureTime(url.getParserFailureTime()+1);
if(url.getParserFailureTime()>20){
logger.error("解析失败连续超过20次url:{} parserName:{} content:{}", url.getUrl(),url.getParserClass(), content);//记录错误日志,方便排查问题,改解析代码
return;//不插入进去了,停止该定时任务
}
if(proxy!=null)
logger.error("解析失败 url:{},proxy host:{} proxy port:{},parserName{}", url.getUrl(),proxy.getHost(),proxy.getPort(), url.getParserClass());//记录错误日志,方便排查问题,改解析代码
else
logger.error("解析失败 url:{},parserName{}", url.getUrl(), url.getParserClass());//记录错误日志,方便排查问题,改解析代码
addImmediateTask(getUrl(),500);
}
}
private void addImmediateTask(Url url ,long delay){
long useDelay =timedUrl.getDelay()<delay?timedUrl.getDelay():delay;
timedUrlPool.offer(new Task(url,useDelay));
}
private class Task extends TimedUrlPool.TimedUrl{
private final Url url;
private final long delay;
public Task(Url url, long delay) {
this.url = url;
this.delay = delay;
}
@Override
public Url getUrl() {
return url;
}
@Override
public long getDelay() {
return delay;
}
}
}