Skip to content

Commit 5a5b0b4

Browse files
fix OS Utils Pc Session start method, should work for all OS
Signed-off-by: nkomonen-amazon <[email protected]>
1 parent 11fabbb commit 5a5b0b4

File tree

2 files changed

+62
-63
lines changed

2 files changed

+62
-63
lines changed

packages/core/src/shared/utilities/osUtils.ts

Lines changed: 19 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44
*/
55

66
import globals from '../extensionGlobals'
7-
import { fs } from '../fs/fs'
8-
import { tempDirPath } from '../filesystemUtilities'
9-
import path from 'path'
10-
import { getExtensionId } from '../extensionUtilities'
7+
import * as os from 'os'
118

129
/**
1310
* Checks if the current OS session is new.
@@ -18,44 +15,24 @@ import { getExtensionId } from '../extensionUtilities'
1815
* Use this function to perform one-time initialization tasks that should only happen
1916
* once per OS session, regardless of how many extension instances are running.
2017
*/
21-
export async function isNewOsSession(tmpDir = tempDirPath) {
22-
switch (process.platform) {
23-
case 'win32': {
24-
// Windows does not have an ephemeral /tmp/ folder that deletes on shutdown, while unix-like os's do.
25-
// So in Windows we calculate the start time and see if it changed from the previous known start time.
26-
27-
const lastStartTime = globals.globalState.tryGet('lastOsStartTime', Number)
28-
// uptime() returns seconds, convert to ms
29-
const currentOsStartTime = Date.now() - process.uptime() * 1000
30-
31-
if (lastStartTime === undefined) {
32-
await globals.globalState.update('lastOsStartTime', currentOsStartTime)
33-
return true
34-
}
35-
36-
// If the current start time is later than the last, it means we are in a new session
37-
// But remove a few seconds to account for a small delay between getting the current time and
38-
// actually comparing it.
39-
if (currentOsStartTime - 2000 > lastStartTime) {
40-
await globals.globalState.update('lastOsStartTime', currentOsStartTime)
41-
return true
42-
}
43-
44-
return false
45-
}
46-
default: {
47-
// Store a file in /tmp/ that acts as a flag. The OS automatically deletes on system shutdown.
48-
const unixNewSessionPath = path.join(tmpDir, `sessionStart-${getExtensionId()}`)
49-
50-
if (await fs.exists(unixNewSessionPath)) {
51-
return false
52-
}
18+
export async function isNewOsSession(now = () => globals.clock.Date.now(), uptime = () => os.uptime()) {
19+
// Windows does not have an ephemeral /tmp/ folder that deletes on shutdown, while unix-like os's do.
20+
// So in Windows we calculate the start time and see if it changed from the previous known start time.
21+
const lastStartTime = globals.globalState.tryGet('lastOsStartTime', Number)
22+
// uptime() returns seconds, convert to ms
23+
const currentOsStartTime = now() - uptime() * 1000 * 60
24+
25+
if (lastStartTime === undefined) {
26+
await globals.globalState.update('lastOsStartTime', currentOsStartTime)
27+
return true
28+
}
5329

54-
await fs.writeFile(
55-
unixNewSessionPath,
56-
`This file is autogenerated by the VS Code extension: ${getExtensionId()}`
57-
)
58-
return true
59-
}
30+
// If the current start time is later than the last, it means we are in a new session since they should be the same value.
31+
// But to account for small differences in how the current time is calculate, we add in a 5 second buffer.
32+
if (currentOsStartTime - 1000 * 5 > lastStartTime) {
33+
await globals.globalState.update('lastOsStartTime', currentOsStartTime)
34+
return true
6035
}
36+
37+
return false
6138
}

packages/core/src/test/shared/utilities/osUtils.test.ts

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,49 @@
55

66
import assert from 'assert'
77
import { isNewOsSession } from '../../../shared/utilities/osUtils'
8-
import { fs } from '../../../shared'
9-
import { isWin } from '../../../shared/vscode/env'
10-
import { TestFolder } from '../../testUtil'
8+
import { InstalledClock } from '@sinonjs/fake-timers'
9+
import { createSandbox, SinonSandbox } from 'sinon'
1110

1211
describe('isNewOsSession', () => {
13-
if (!isWin()) {
14-
it('unix-like: returns true when expected', async () => {
15-
const tmpDir = (await TestFolder.create()).path
16-
17-
// On a new session the first caller will get true
18-
assert.strictEqual(await isNewOsSession(tmpDir), true)
19-
// Subsequent callers will get false
20-
assert.strictEqual(await isNewOsSession(tmpDir), false)
21-
22-
// Mimic a fresh restart (/tmp/ folder is deleted)
23-
const files = await fs.readdir(tmpDir)
24-
await Promise.all(files.map(async (file) => await fs.delete(`${tmpDir}/${file[0]}`)))
25-
26-
// Since the tmp/ folder was cleared it is considered a new session
27-
assert.strictEqual(await isNewOsSession(tmpDir), true)
28-
assert.strictEqual(await isNewOsSession(tmpDir), false)
29-
})
30-
}
12+
let clock: InstalledClock | undefined
13+
let sandbox: SinonSandbox
14+
15+
beforeEach(function () {
16+
sandbox = createSandbox()
17+
})
18+
19+
afterEach(function () {
20+
clock?.uninstall()
21+
sandbox.restore()
22+
})
23+
24+
it('unix-like: returns true when expected', async () => {
25+
const uptimeStub = sandbox.stub()
26+
const now = sandbox.stub()
27+
// We started our computer at 2 minutes since epoch (time - pc uptime)
28+
// and the comptuer has been on for 1 minute. So the OS started 1 minute since epoch.
29+
now.returns(60_000 + 60_000)
30+
uptimeStub.returns(1)
31+
32+
// On a brand new session the first caller will get true
33+
assert.strictEqual(await isNewOsSession(now, uptimeStub), true)
34+
// Subsequent callers will get false
35+
assert.strictEqual(await isNewOsSession(now, uptimeStub), false)
36+
37+
// Start a computer session 10 minutes from epoch
38+
uptimeStub.returns(0)
39+
now.returns(60_000 * 10)
40+
assert.strictEqual(await isNewOsSession(now, uptimeStub), true)
41+
// Anything that is within a 5 second threshold of the last session time, is considered the same session
42+
now.returns(60_000 * 10 + 5000)
43+
assert.strictEqual(await isNewOsSession(now, uptimeStub), false)
44+
now.returns(60_000 * 10 + 5000 + 1)
45+
assert.strictEqual(await isNewOsSession(now, uptimeStub), true)
46+
47+
// A non-zero uptime
48+
uptimeStub.returns(5) // The computer has been running for 5 minutes already, so the start time is relative to this.
49+
now.returns(60_000 * 10 + 5000 + 60_000 * 10) // 5 minutes since last session
50+
// Nothing changes since the diff between uptime and the last start has not changed
51+
assert.strictEqual(await isNewOsSession(now, uptimeStub), true)
52+
})
3153
})

0 commit comments

Comments
 (0)