Skip to content

Commit

Permalink
Support set Elm app state using CLI
Browse files Browse the repository at this point in the history
Also, fix a problem in the server implementation to check if the serialized representation is compatible with the Elm type: Do not depend on the formatting in the JSON.
  • Loading branch information
Viir committed May 11, 2020
1 parent a7c0f67 commit 012e148
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ Composition.TreeComponent loadComponentFromStoreAndAssertIsTree(string component
var resultingElmAppState = processBefore.lastElmAppVolatileProcess.GetSerializedState();

var lastSetElmAppStateResult =
resultingElmAppState == projectedElmAppState
applyCommonFormattingToJson(resultingElmAppState) == applyCommonFormattingToJson(projectedElmAppState)
?
new Result<string, string>
{
Expand Down Expand Up @@ -645,7 +645,7 @@ Ok valueToEncodeOk ->

var resultingState = testProcess.GetSerializedState();

if (resultingState != elmAppStateMigratedSerialized)
if (applyCommonFormattingToJson(resultingState) != applyCommonFormattingToJson(elmAppStateMigratedSerialized))
return new Result<string, string>
{
Err = "Failed to load the migrated serialized state with the destination public app configuration. resulting State:\n" + resultingState
Expand Down Expand Up @@ -707,6 +707,18 @@ public string ProcessElmAppEvent(IProcessStoreWriter storeWriter, string seriali
}
}

static string applyCommonFormattingToJson(string originalJson)
{
try
{
return Newtonsoft.Json.JsonConvert.SerializeObject(Newtonsoft.Json.JsonConvert.DeserializeObject(originalJson));
}
catch
{
return originalJson;
}
}

public void Dispose() => lastElmAppVolatileProcess?.Dispose();

public ProvisionalReductionRecordInFile StoreReductionRecordForCurrentState(IProcessStoreWriter storeWriter)
Expand Down
111 changes: 110 additions & 1 deletion implement/elm-fullstack/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,30 @@ CommandOption verboseLogOptionFromCommand(CommandLineApplication command) =>
});
});

app.Command("set-elm-app-state", setElmAppStateCmd =>
{
setElmAppStateCmd.Description = "Attempt to set the state of a backend Elm app using the common serialized representation.";

var siteAndPasswordFromCmd = siteAndSitePasswordOptionsOnCommand(setElmAppStateCmd);

var sourceOption = setElmAppStateCmd.Option("--source", "Source to load the serialized state representation from.", CommandOptionType.SingleValue).IsRequired(allowEmptyStrings: false);

setElmAppStateCmd.OnExecute(() =>
{
var (site, sitePassword) = siteAndPasswordFromCmd();

var attemptReport =
setElmAppState(
site: site,
sitePassword: sitePassword,
source: sourceOption.Value());

writeReportToFileInReportDirectory(
reportContent: Newtonsoft.Json.JsonConvert.SerializeObject(attemptReport, Newtonsoft.Json.Formatting.Indented),
reportKind: "set-elm-app-state.json");
});
});

app.Command("truncate-process-history", truncateProcessHistoryCmd =>
{
var siteAndPasswordFromCmd = siteAndSitePasswordOptionsOnCommand(truncateProcessHistoryCmd);
Expand Down Expand Up @@ -358,6 +382,91 @@ static DeployAppConfigReport deployAppConfig(string site, string sitePassword, b
};
}

class SetElmAppStateReport
{
public string beginTime;

public string elmAppStateSource;

public string elmAppStateId;

public string site;

public ResponseFromServerStruct responseFromServer;

public int totalTimeSpentMilli;

public class ResponseFromServerStruct
{
public int? statusCode;

public object body;
}
}

static SetElmAppStateReport setElmAppState(string site, string sitePassword, string source)
{
var beginTime = DateTimeOffset.UtcNow.ToString("yyyy-MM-ddTHH-mm-ss");

var totalStopwatch = System.Diagnostics.Stopwatch.StartNew();

// For now only support a file path as source.

var elmAppStateSerialized = File.ReadAllBytes(source);

var elmAppStateComponent = Composition.Component.Blob(elmAppStateSerialized);

var elmAppStateId = CommonConversion.StringBase16FromByteArray(Composition.GetHash(elmAppStateComponent));

SetElmAppStateReport.ResponseFromServerStruct responseFromServer = null;

using (var httpClient = new System.Net.Http.HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(
Kalmit.PersistentProcess.WebHost.Configuration.BasicAuthenticationForAdminRoot(sitePassword))));

var httpContent = new System.Net.Http.ByteArrayContent(elmAppStateSerialized);

httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");

var httpResponse = httpClient.PostAsync(
site.TrimEnd('/') + StartupAdminInterface.PathApiElmAppState, httpContent).Result;

var responseContentString = httpResponse.Content.ReadAsStringAsync().Result;

Console.WriteLine(
"Server response: " + httpResponse.StatusCode + "\n" +
responseContentString);

object responseBodyReport = responseContentString;

try
{
responseBodyReport =
Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(responseContentString);
}
catch { }

responseFromServer = new SetElmAppStateReport.ResponseFromServerStruct
{
statusCode = (int)httpResponse.StatusCode,
body = responseBodyReport,
};
}

return new SetElmAppStateReport
{
beginTime = beginTime,
elmAppStateSource = source,
elmAppStateId = elmAppStateId,
site = site,
responseFromServer = responseFromServer,
totalTimeSpentMilli = (int)totalStopwatch.ElapsedMilliseconds,
};
}

class TruncateProcessHistoryReport
{
public string site;
Expand Down Expand Up @@ -603,7 +712,7 @@ static void writeReportToFileInReportDirectory(string reportContent, string repo

Directory.CreateDirectory(Path.GetDirectoryName(filePath));

File.WriteAllText(filePath, reportContent, System.Text.Encoding.UTF8);
File.WriteAllBytes(filePath, System.Text.Encoding.UTF8.GetBytes(reportContent));

Console.WriteLine("Saved report to file '" + filePath + "'.");
}
Expand Down

0 comments on commit 012e148

Please sign in to comment.