Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit312ac1a

Browse files
authored
Merge pull requestcoderoad#526 from coderoad/fallback-to-file
fallback session state to file
2 parentsd01b0d2 +ba4e1ac commit312ac1a

File tree

7 files changed

+77
-8
lines changed

7 files changed

+77
-8
lines changed

‎docs/docs/env-vars.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ CodeRoad has a number of configurations:
2020

2121
-`CODEROAD_WEBHOOK_TOKEN` - an optional token for authenticating/authorizing webhook endpoints. Passed to the webhook endpoint in a`CodeRoad-User-Token` header.
2222

23+
-`CODEROAD_SESSION_STORAGE_PATH` - the path to a directory for writing session storage to files. Helps preserves state across containers. Example:`../tmp`.
24+
2325
##How to Use Variables
2426

2527
###Local

‎src/actions/onStartup.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ const onStartup = async (context: Context): Promise<void> => {
3535

3636
// NEW: no stored tutorial, must start new tutorial
3737
if(!tutorial||!tutorial.id){
38-
if(!!TUTORIAL_URL){
39-
//NEW_FROM_URL
38+
if(TUTORIAL_URL){
39+
//if a tutorial URL is added, launch on startup
4040
try{
4141
consttutorialRes=awaitfetch(TUTORIAL_URL)
4242
consttutorial=awaittutorialRes.json()

‎src/environment.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,6 @@ export const CONTENT_SECURITY_POLICY_EXEMPTIONS: string | null =
4646

4747
// optional token for authorization/authentication of webhook calls
4848
exportconstWEBHOOK_TOKEN=process.env.CODEROAD_WEBHOOK_TOKEN||null
49+
50+
// a path to write session state to a file. Useful for maintaining session across containers
51+
exportconstSESSION_STORAGE_PATH=process.env.CODEROAD_SESSION_STORAGE_PATH||null

‎src/services/context/state/Position.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class Position {
1919
setTutorial(workspaceState:vscode.Memento,tutorial:TT.Tutorial):void{
2020
this.storage=newStorage<T.Position>({
2121
key:`coderoad:position:${tutorial.id}:${tutorial.version}`,
22+
filePath:'coderoad_position',
2223
storage:workspaceState,
2324
defaultValue,
2425
})

‎src/services/context/state/Tutorial.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ class Tutorial {
99
constructor(workspaceState:vscode.Memento){
1010
this.storage=newStorage<TT.Tutorial|null>({
1111
key:'coderoad:currentTutorial',
12+
filePath:'coderoad_tutorial',
1213
storage:workspaceState,
1314
defaultValue:null,
1415
})

‎src/services/node/index.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,41 @@ import { WORKSPACE_ROOT } from '../../environment'
77
constasyncExec=promisify(cpExec)
88
constasyncRemoveFile=promisify(fs.unlink)
99
constasyncReadFile=promisify(fs.readFile)
10+
constasyncWriteFile=promisify(fs.writeFile)
1011

1112
interfaceExecParams{
1213
command:string
1314
dir?:string
1415
}
1516

17+
// correct paths to be from workspace root rather than extension folder
18+
constgetWorkspacePath=(...paths:string[])=>{
19+
returnjoin(WORKSPACE_ROOT, ...paths)
20+
}
21+
1622
exportconstexec=(params:ExecParams):Promise<{stdout:string;stderr:string}>|never=>{
1723
constcwd=join(WORKSPACE_ROOT,params.dir||'')
1824
returnasyncExec(params.command,{ cwd})
1925
}
2026

2127
exportconstexists=(...paths:string[]):boolean|never=>{
22-
returnfs.existsSync(join(WORKSPACE_ROOT,...paths))
28+
returnfs.existsSync(getWorkspacePath(...paths))
2329
}
2430

2531
exportconstremoveFile=(...paths:string[])=>{
26-
returnasyncRemoveFile(join(WORKSPACE_ROOT, ...paths))
32+
returnasyncRemoveFile(getWorkspacePath(...paths))
33+
}
34+
35+
exportconstreadFile=(...paths:string[]):Promise<string|void>=>{
36+
constfilePath=getWorkspacePath(...paths)
37+
returnasyncReadFile(getWorkspacePath(...paths),'utf8').catch((err)=>{
38+
console.warn(`Failed to read from${filePath}:${err.message}`)
39+
})
2740
}
2841

29-
exportconstreadFile=(...paths:string[])=>{
30-
returnasyncReadFile(join(...paths))
42+
exportconstwriteFile=(data:any, ...paths:string[]):Promise<void>=>{
43+
constfilePath=getWorkspacePath(...paths)
44+
returnasyncWriteFile(filePath,data).catch((err)=>{
45+
console.warn(`Failed to write to${filePath}:${err.message}`)
46+
})
3147
}

‎src/services/storage/index.ts

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import*asvscodefrom'vscode'
2+
import{readFile,writeFile}from'../node'
3+
import{SESSION_STORAGE_PATH}from'../../environment'
24

35
// NOTE: localStorage is not available on client
46
// and must be stored in editor
@@ -8,31 +10,75 @@ import * as vscode from 'vscode'
810
// forcing it to be passed in through activation and down to other tools
911
classStorage<T>{
1012
privatekey:string
13+
privatefilePath:string
1114
privatestorage:vscode.Memento
1215
privatedefaultValue:T
13-
constructor({ key, storage, defaultValue}:{key:string;storage:vscode.Memento;defaultValue:T}){
16+
constructor({
17+
key,
18+
filePath,
19+
storage,
20+
defaultValue,
21+
}:{
22+
key:string
23+
filePath:string
24+
storage:vscode.Memento
25+
defaultValue:T
26+
}){
1427
this.storage=storage
1528
this.key=key
29+
this.filePath=filePath
1630
this.defaultValue=defaultValue
1731
}
1832
publicget=async():Promise<T>=>{
1933
constvalue:string|undefined=awaitthis.storage.get(this.key)
2034
if(value){
2135
returnJSON.parse(value)
36+
}elseif(SESSION_STORAGE_PATH){
37+
try{
38+
// optionally read from file as a fallback to local storage
39+
constsessionFile=awaitreadFile(SESSION_STORAGE_PATH,`${this.filePath}.json`)
40+
if(!sessionFile){
41+
thrownewError('No session file found')
42+
}
43+
constdata:T=JSON.parse(sessionFile)
44+
45+
if(data){
46+
// validate session
47+
constkeys=Object.keys(data)
48+
if(keys.length){
49+
returndata
50+
}
51+
}
52+
}catch(err){
53+
console.warn(`Failed to read or parse session file:${SESSION_STORAGE_PATH}/${this.filePath}.json`)
54+
}
2255
}
2356
returnthis.defaultValue
2457
}
2558
publicset=(value:T):void=>{
2659
conststringValue=JSON.stringify(value)
2760
this.storage.update(this.key,stringValue)
61+
this.writeToSessionFile(stringValue)
2862
}
2963
publicupdate=async(value:T):Promise<void>=>{
3064
constcurrent=awaitthis.get()
3165
constnext=JSON.stringify({
3266
...current,
3367
...value,
3468
})
35-
this.storage.update(this.key,next)
69+
awaitthis.storage.update(this.key,next)
70+
71+
this.writeToSessionFile(next)
72+
}
73+
publicwriteToSessionFile(data:string){
74+
// optionally write state to file, useful when state cannot be controlled across containers
75+
if(SESSION_STORAGE_PATH){
76+
try{
77+
writeFile(data,SESSION_STORAGE_PATH,`${this.filePath}.json`)
78+
}catch(err:any){
79+
console.warn(`Failed to write coderoad session to path:${SESSION_STORAGE_PATH}/${this.filePath}.json`)
80+
}
81+
}
3682
}
3783
publicreset=()=>{
3884
this.set(this.defaultValue)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp