mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-29 07:23:43 -05:00
Improve logging around main operations.
PostbackManager.java: check for actual postback promise before waiting.
This commit is contained in:
parent
ab09d044a8
commit
08f3497a9e
9 changed files with 196 additions and 47 deletions
|
@ -7,8 +7,8 @@ import org.eclipse.jgit.transport.ServiceMayNotContinueException;
|
|||
import uk.ac.ic.wlgitbridge.data.CandidateSnapshot;
|
||||
import uk.ac.ic.wlgitbridge.data.ProjectLock;
|
||||
import uk.ac.ic.wlgitbridge.data.ShutdownHook;
|
||||
import uk.ac.ic.wlgitbridge.data.model.DataStore;
|
||||
import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
|
||||
import uk.ac.ic.wlgitbridge.data.model.DataStore;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocRequest;
|
||||
|
@ -18,7 +18,6 @@ import uk.ac.ic.wlgitbridge.snapshot.push.PushRequest;
|
|||
import uk.ac.ic.wlgitbridge.snapshot.push.PushResult;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.*;
|
||||
import uk.ac.ic.wlgitbridge.util.Log;
|
||||
import uk.ac.ic.wlgitbridge.util.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -72,7 +71,7 @@ public class BridgeAPI {
|
|||
SnapshotPostException,
|
||||
GitAPIException,
|
||||
ForbiddenException {
|
||||
Util.sout("Fetching project: " + projectName);
|
||||
Log.info("[{}] Fetching", projectName);
|
||||
dataStore.updateProjectWithName(oauth2, projectName, repository);
|
||||
}
|
||||
|
||||
|
@ -86,19 +85,24 @@ public class BridgeAPI {
|
|||
mainProjectLock.lockForProject(projectName);
|
||||
CandidateSnapshot candidate = null;
|
||||
try {
|
||||
Log.info("[Project {}] Pushing", projectName);
|
||||
Log.info("[{}] Pushing", projectName);
|
||||
String postbackKey = postbackManager.makeKeyForProject(projectName);
|
||||
Log.info(
|
||||
"[Project {}] Created postback key: {}",
|
||||
"[{}] Created postback key: {}",
|
||||
projectName,
|
||||
postbackKey
|
||||
);
|
||||
candidate =
|
||||
dataStore.createCandidateSnapshotFromProjectWithContents(
|
||||
dataStore.createCandidateSnapshot(
|
||||
projectName,
|
||||
directoryContents,
|
||||
oldDirectoryContents
|
||||
);
|
||||
Log.info(
|
||||
"[{}] Candindate snapshot created: {}",
|
||||
projectName,
|
||||
candidate
|
||||
);
|
||||
PushRequest pushRequest = new PushRequest(
|
||||
oauth2,
|
||||
candidate,
|
||||
|
@ -108,39 +112,52 @@ public class BridgeAPI {
|
|||
PushResult result = pushRequest.getResult();
|
||||
if (result.wasSuccessful()) {
|
||||
Log.info(
|
||||
"[Project {}] Push to Overleaf successful",
|
||||
"[{}] Push to Overleaf successful",
|
||||
projectName
|
||||
);
|
||||
Log.info("[Project {}] Waiting for postback...", projectName);
|
||||
Log.info("[{}] Waiting for postback...", projectName);
|
||||
int versionID =
|
||||
postbackManager.waitForVersionIdOrThrow(projectName);
|
||||
Log.info(
|
||||
"[Project {}] Got version ID for push: {}",
|
||||
"[{}] Got version ID for push: {}",
|
||||
projectName,
|
||||
versionID
|
||||
);
|
||||
dataStore.approveSnapshot(versionID, candidate);
|
||||
Log.info(
|
||||
"[Project {}] Approved version ID: {}",
|
||||
"[{}] Approved version ID: {}",
|
||||
projectName,
|
||||
versionID
|
||||
);
|
||||
} else {
|
||||
Log.warn(
|
||||
"[{}] Went out of date while waiting for push",
|
||||
projectName
|
||||
);
|
||||
throw new OutOfDateException();
|
||||
}
|
||||
} catch (SevereSnapshotPostException e) {
|
||||
Log.warn("Failed to put to Overleaf", e);
|
||||
Log.warn("[" + projectName + "] Failed to put to Overleaf", e);
|
||||
throw e;
|
||||
} catch (SnapshotPostException e) {
|
||||
/* Stack trace should be printed further up */
|
||||
Log.warn(
|
||||
"[{}] Exception when waiting for postback: {}",
|
||||
projectName,
|
||||
e.getClass().getSimpleName()
|
||||
);
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
Log.warn("[{}] IOException on put", projectName);
|
||||
throw e;
|
||||
} finally {
|
||||
if (candidate != null) {
|
||||
candidate.deleteServletFiles();
|
||||
} else {
|
||||
Log.error(
|
||||
"Candidate snapshot was null: this should never happen."
|
||||
"[{}] Candidate snapshot was null: " +
|
||||
"this should never happen.",
|
||||
projectName
|
||||
);
|
||||
}
|
||||
mainProjectLock.unlockForProject(projectName);
|
||||
|
@ -157,13 +174,23 @@ public class BridgeAPI {
|
|||
String postbackKey,
|
||||
int versionID)
|
||||
throws UnexpectedPostbackException {
|
||||
postbackManager.postVersionIDForProject(projectName, versionID, postbackKey);
|
||||
Log.info(
|
||||
"[{}]" +
|
||||
" Postback received by postback thread, version: {}",
|
||||
projectName,
|
||||
versionID);
|
||||
postbackManager.postVersionIDForProject(
|
||||
projectName,
|
||||
versionID,
|
||||
postbackKey
|
||||
);
|
||||
}
|
||||
|
||||
public void postbackReceivedWithException(String projectName,
|
||||
String postbackKey,
|
||||
SnapshotPostException exception)
|
||||
throws UnexpectedPostbackException {
|
||||
Log.warn("[{}] Postback received with exception", projectName);
|
||||
postbackManager.postExceptionForProject(
|
||||
projectName,
|
||||
exception,
|
||||
|
|
|
@ -76,7 +76,9 @@ public class CandidateSnapshot {
|
|||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("latestVerId", currentVersion);
|
||||
jsonObject.add("files", getFilesAsJson(projectURL, postbackKey));
|
||||
jsonObject.addProperty("postbackUrl", projectURL + "/" + postbackKey + "/postback");
|
||||
jsonObject.addProperty(
|
||||
"postbackUrl", projectURL + "/" + postbackKey + "/postback"
|
||||
);
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
|
@ -105,4 +107,16 @@ public class CandidateSnapshot {
|
|||
return deleted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("VersionId: ");
|
||||
sb.append(currentVersion);
|
||||
sb.append(", files: ");
|
||||
sb.append(files);
|
||||
sb.append(", deleted: ");
|
||||
sb.append(deleted);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,4 +29,9 @@ public class ServletFile extends RawFile {
|
|||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getPath();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package uk.ac.ic.wlgitbridge.data.filestore;
|
||||
|
||||
import uk.ac.ic.wlgitbridge.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -21,6 +23,7 @@ public abstract class RawFile {
|
|||
OutputStream out = new FileOutputStream(file);
|
||||
out.write(getContents());
|
||||
out.close();
|
||||
Log.info("Wrote file: {}", file.getAbsolutePath());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,11 +11,11 @@ import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
|
|||
import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
|
||||
import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
|
||||
import uk.ac.ic.wlgitbridge.data.model.db.PersistentStore;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
|
||||
import uk.ac.ic.wlgitbridge.data.model.db.SqlitePersistentStore;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getforversion.SnapshotAttachment;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.SnapshotPostException;
|
||||
import uk.ac.ic.wlgitbridge.util.Log;
|
||||
import uk.ac.ic.wlgitbridge.util.Util;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -37,35 +37,78 @@ public class DataStore {
|
|||
persistentStore = new SqlitePersistentStore(rootGitDirectory);
|
||||
List<String> excludedFromDeletion = persistentStore.getProjectNames();
|
||||
excludedFromDeletion.add(".wlgb");
|
||||
Util.deleteInDirectoryApartFrom(rootGitDirectory, excludedFromDeletion.toArray(new String[] {}));
|
||||
Util.deleteInDirectoryApartFrom(
|
||||
rootGitDirectory,
|
||||
excludedFromDeletion.toArray(new String[] {})
|
||||
);
|
||||
|
||||
snapshotFetcher = new SnapshotFetcher();
|
||||
resourceFetcher = new ResourceFetcher(persistentStore);
|
||||
}
|
||||
|
||||
public void updateProjectWithName(Credential oauth2, String name, Repository repository) throws IOException, SnapshotPostException, GitAPIException, ForbiddenException {
|
||||
LinkedList<Snapshot> snapshots = snapshotFetcher.getSnapshotsForProjectAfterVersion(oauth2, name, persistentStore.getLatestVersionForProject(name));
|
||||
public void updateProjectWithName(Credential oauth2,
|
||||
String name,
|
||||
Repository repository)
|
||||
throws IOException,
|
||||
SnapshotPostException,
|
||||
GitAPIException,
|
||||
ForbiddenException {
|
||||
LinkedList<Snapshot> snapshots =
|
||||
snapshotFetcher.getSnapshotsForProjectAfterVersion(
|
||||
oauth2,
|
||||
name,
|
||||
persistentStore.getLatestVersionForProject(name)
|
||||
);
|
||||
|
||||
makeCommitsFromSnapshots(name, repository, snapshots);
|
||||
|
||||
if (!snapshots.isEmpty()) {
|
||||
persistentStore.setLatestVersionForProject(name, snapshots.getLast().getVersionID());
|
||||
persistentStore.setLatestVersionForProject(
|
||||
name,
|
||||
snapshots.getLast().getVersionID()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void makeCommitsFromSnapshots(String name, Repository repository, List<Snapshot> snapshots) throws IOException, GitAPIException, SnapshotPostException {
|
||||
private void makeCommitsFromSnapshots(String name,
|
||||
Repository repository,
|
||||
List<Snapshot> snapshots)
|
||||
throws IOException, GitAPIException, SnapshotPostException {
|
||||
for (Snapshot snapshot : snapshots) {
|
||||
List<RawFile> files = new LinkedList<RawFile>();
|
||||
files.addAll(snapshot.getSrcs());
|
||||
Map<String, byte[]> fetchedUrls = new HashMap<String, byte[]>();
|
||||
for (SnapshotAttachment snapshotAttachment : snapshot.getAtts()) {
|
||||
files.add(resourceFetcher.get(name, snapshotAttachment.getUrl(), snapshotAttachment.getPath(), repository, fetchedUrls));
|
||||
files.add(
|
||||
resourceFetcher.get(
|
||||
name,
|
||||
snapshotAttachment.getUrl(),
|
||||
snapshotAttachment.getPath(),
|
||||
repository,
|
||||
fetchedUrls
|
||||
)
|
||||
);
|
||||
}
|
||||
commit(name, new GitDirectoryContents(files, rootGitDirectory, name, snapshot), repository);
|
||||
Log.info(
|
||||
"[{}] Committing version ID: {}",
|
||||
name,
|
||||
snapshot.getVersionID()
|
||||
);
|
||||
commit(name,
|
||||
new GitDirectoryContents(
|
||||
files,
|
||||
rootGitDirectory,
|
||||
name,
|
||||
snapshot),
|
||||
repository);
|
||||
}
|
||||
}
|
||||
|
||||
private void commit(String name, GitDirectoryContents contents, Repository repository) throws IOException, GitAPIException {
|
||||
private void commit(String name,
|
||||
GitDirectoryContents contents,
|
||||
Repository repository) throws IOException,
|
||||
GitAPIException {
|
||||
Log.info("[{}] Writing commit", name);
|
||||
contents.write();
|
||||
Git git = new Git(repository);
|
||||
Set<String> missingFiles = git.status().call().getMissing();
|
||||
|
@ -73,26 +116,56 @@ public class DataStore {
|
|||
git.rm().setCached(true).addFilepattern(missing).call();
|
||||
}
|
||||
git.add().addFilepattern(".").call();
|
||||
git.commit().setAuthor(new PersonIdent(contents.getUserName(), contents.getUserEmail(), contents.getWhen(), TimeZone.getDefault()))
|
||||
.setMessage(contents.getCommitMessage())
|
||||
.call();
|
||||
persistentStore.deleteFilesForProject(name, missingFiles.toArray(new String[missingFiles.size()]));
|
||||
git.commit(
|
||||
).setAuthor(
|
||||
new PersonIdent(
|
||||
contents.getUserName(),
|
||||
contents.getUserEmail(),
|
||||
contents.getWhen(),
|
||||
TimeZone.getDefault()
|
||||
)
|
||||
).setMessage(
|
||||
contents.getCommitMessage()
|
||||
).call();
|
||||
persistentStore.deleteFilesForProject(
|
||||
name,
|
||||
missingFiles.toArray(new String[missingFiles.size()])
|
||||
);
|
||||
Log.info(
|
||||
"[{}] Deleting files in directory: {}",
|
||||
name,
|
||||
contents.getDirectory().getAbsolutePath()
|
||||
);
|
||||
Util.deleteInDirectoryApartFrom(contents.getDirectory(), ".git");
|
||||
}
|
||||
|
||||
public CandidateSnapshot createCandidateSnapshotFromProjectWithContents(String projectName, RawDirectory directoryContents, RawDirectory oldDirectoryContents) throws SnapshotPostException, IOException, FailedConnectionException {
|
||||
CandidateSnapshot candidateSnapshot = new CandidateSnapshot(projectName,
|
||||
public CandidateSnapshot
|
||||
createCandidateSnapshot(String projectName,
|
||||
RawDirectory directoryContents,
|
||||
RawDirectory oldDirectoryContents)
|
||||
throws SnapshotPostException,
|
||||
IOException {
|
||||
CandidateSnapshot candidateSnapshot = new CandidateSnapshot(
|
||||
projectName,
|
||||
persistentStore.getLatestVersionForProject(projectName),
|
||||
directoryContents,
|
||||
oldDirectoryContents);
|
||||
oldDirectoryContents
|
||||
);
|
||||
candidateSnapshot.writeServletFiles(rootGitDirectory);
|
||||
return candidateSnapshot;
|
||||
}
|
||||
|
||||
public void approveSnapshot(int versionID, CandidateSnapshot candidateSnapshot) {
|
||||
public void approveSnapshot(int versionID,
|
||||
CandidateSnapshot candidateSnapshot) {
|
||||
List<String> deleted = candidateSnapshot.getDeleted();
|
||||
persistentStore.setLatestVersionForProject(candidateSnapshot.getProjectName(), versionID);
|
||||
persistentStore.deleteFilesForProject(candidateSnapshot.getProjectName(), deleted.toArray(new String[deleted.size()]));
|
||||
persistentStore.setLatestVersionForProject(
|
||||
candidateSnapshot.getProjectName(),
|
||||
versionID
|
||||
);
|
||||
persistentStore.deleteFilesForProject(
|
||||
candidateSnapshot.getProjectName(),
|
||||
deleted.toArray(new String[deleted.size()])
|
||||
);
|
||||
}
|
||||
|
||||
private File initRootGitDirectory(String rootGitDirectoryPath) {
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package uk.ac.ic.wlgitbridge.data.model.db;
|
||||
|
||||
import uk.ac.ic.wlgitbridge.data.model.db.sql.SQLiteWLDatabase;
|
||||
import uk.ac.ic.wlgitbridge.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -35,6 +37,7 @@ public class SqlitePersistentStore implements PersistentStore {
|
|||
public void setLatestVersionForProject(String project, int versionID) {
|
||||
try {
|
||||
database.setVersionIDForProject(project, versionID);
|
||||
Log.info("[{}] Wrote latest versionId: {}", project, versionID);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -53,6 +56,7 @@ public class SqlitePersistentStore implements PersistentStore {
|
|||
public void addURLIndexForProject(String projectName, String url, String path) {
|
||||
try {
|
||||
database.addURLIndex(projectName, url, path);
|
||||
Log.info("[{}] Wrote url index: {} -> {}", projectName, url, path);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -62,6 +66,11 @@ public class SqlitePersistentStore implements PersistentStore {
|
|||
public void deleteFilesForProject(String project, String... files) {
|
||||
try {
|
||||
database.deleteFilesForProject(project, files);
|
||||
Log.info(
|
||||
"[{}] Deleting from url index: {}",
|
||||
project,
|
||||
Arrays.toString(files)
|
||||
);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package uk.ac.ic.wlgitbridge.snapshot.push;
|
||||
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.InvalidPostbackKeyException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.SnapshotPostException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.UnexpectedPostbackException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.*;
|
||||
import uk.ac.ic.wlgitbridge.util.Log;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
|
@ -22,25 +21,41 @@ public class PostbackManager {
|
|||
postbackContentsTable = new HashMap<String, PostbackPromise>();
|
||||
}
|
||||
|
||||
public int waitForVersionIdOrThrow(String projectName) throws SnapshotPostException {
|
||||
public int waitForVersionIdOrThrow(String projectName)
|
||||
throws SnapshotPostException {
|
||||
try {
|
||||
return postbackContentsTable.get(projectName).waitForPostback();
|
||||
} catch (SnapshotPostException e) {
|
||||
throw e;
|
||||
PostbackPromise postbackPromise =
|
||||
postbackContentsTable.get(projectName);
|
||||
if (postbackPromise == null) {
|
||||
Log.warn("[{}] PostbackPromise was null.", projectName);
|
||||
throw new InternalErrorException();
|
||||
}
|
||||
return postbackPromise.waitForPostback();
|
||||
} finally {
|
||||
postbackContentsTable.remove(projectName);
|
||||
}
|
||||
}
|
||||
|
||||
public void postVersionIDForProject(String projectName, int versionID, String postbackKey) throws UnexpectedPostbackException {
|
||||
getPostbackForProject(projectName).receivedVersionID(versionID, postbackKey);
|
||||
public void postVersionIDForProject(String projectName,
|
||||
int versionID,
|
||||
String postbackKey)
|
||||
throws UnexpectedPostbackException {
|
||||
getPostbackForProject(
|
||||
projectName
|
||||
).receivedVersionID(versionID, postbackKey);
|
||||
}
|
||||
|
||||
public void postExceptionForProject(String projectName, SnapshotPostException exception, String postbackKey) throws UnexpectedPostbackException {
|
||||
getPostbackForProject(projectName).receivedException(exception, postbackKey);
|
||||
public void postExceptionForProject(String projectName,
|
||||
SnapshotPostException exception,
|
||||
String postbackKey)
|
||||
throws UnexpectedPostbackException {
|
||||
getPostbackForProject(
|
||||
projectName
|
||||
).receivedException(exception, postbackKey);
|
||||
}
|
||||
|
||||
private PostbackPromise getPostbackForProject(String projectName) throws UnexpectedPostbackException {
|
||||
private PostbackPromise getPostbackForProject(String projectName)
|
||||
throws UnexpectedPostbackException {
|
||||
PostbackPromise contents = postbackContentsTable.remove(projectName);
|
||||
if (contents == null) {
|
||||
throw new UnexpectedPostbackException();
|
||||
|
@ -55,7 +70,8 @@ public class PostbackManager {
|
|||
return key;
|
||||
}
|
||||
|
||||
public void checkPostbackKey(String projectName, String postbackKey) throws InvalidPostbackKeyException {
|
||||
public void checkPostbackKey(String projectName, String postbackKey)
|
||||
throws InvalidPostbackKeyException {
|
||||
postbackContentsTable.get(projectName).checkPostbackKey(postbackKey);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ public class Log {
|
|||
static {
|
||||
System.setProperty(SimpleLogger.SHOW_DATE_TIME_KEY, "true");
|
||||
System.setProperty(SimpleLogger.DATE_TIME_FORMAT_KEY, "yyyy-MM-dd HH:mm:ss:SSS Z");
|
||||
System.setProperty(SimpleLogger.SHOW_SHORT_LOG_NAME_KEY, "true");
|
||||
}
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(GitBridgeApp.class);
|
||||
|
|
|
@ -144,6 +144,7 @@ public class Util {
|
|||
deleteInDirectory(file);
|
||||
}
|
||||
file.delete();
|
||||
Log.info("Deleted file: {}", file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue