Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
appbase-edge-function
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
duanjinfei
appbase-edge-function
Commits
ef4c305c
Commit
ef4c305c
authored
Nov 25, 2024
by
duanjinfei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
clean up storage
parent
4e1d8e24
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
144 additions
and
67 deletions
+144
-67
index.ts
supabase/functions/cleanup-storage/index.ts
+144
-67
No files found.
supabase/functions/cleanup-storage/index.ts
View file @
ef4c305c
// Follow this setup guide to integrate the Deno language server with your editor:
// https://deno.land/manual/getting_started/setup_your_environment
// This enables autocomplete, go to definition, etc.
import
"
jsr:@supabase/functions-js/edge-runtime.d.ts
"
;
import
{
createClient
}
from
"
jsr:@supabase/supabase-js@2
"
;
// Setup type definitions for built-in Supabase Runtime APIs
import
"
jsr:@supabase/functions-js/edge-runtime.d.ts
"
import
{
createClient
}
from
'
jsr:@supabase/supabase-js@2
'
const
corsHeaders
=
{
"
Access-Control-Allow-Origin
"
:
"
*
"
,
"
Access-Control-Allow-Headers
"
:
"
authorization, content-type
"
,
"
Access-Control-Allow-Methods
"
:
"
GET, POST, OPTIONS
"
,
};
// 删除目录和其下的文件
async
function
deleteDirectory
(
bucket
:
string
,
directory
:
string
)
{
// 删除指定目录及其下的文件
async
function
deleteDirectory
(
supabase
,
bucket
:
string
,
directory
:
string
)
{
try
{
const
{
data
,
error
}
=
await
supabase
.
storage
.
from
(
bucket
).
list
(
directory
,
{
limit
:
1000
,
// 批量获取文件
limit
:
1000
,
});
if
(
error
)
{
...
...
@@ -27,63 +29,138 @@ async function deleteDirectory(bucket: string, directory: string) {
console
.
log
(
`Successfully deleted directory "
${
directory
}
" and its contents.`
);
}
}
}
catch
(
err
)
{
console
.
error
(
`Error deleting directory "
${
directory
}
":`
,
err
);
}
}
// 获取需要删除的时间戳目录
function
getOldDirectories
(
currentTimestamp
:
string
,
interval
:
"
hour
"
|
"
day
"
,
keepCount
:
number
)
{
const
now
=
new
Date
(
currentTimestamp
);
// 获取当前整点时间
function
getCurrentHourTimestamp
():
Date
{
const
now
=
new
Date
();
return
new
Date
(
now
.
getFullYear
(),
now
.
getMonth
(),
now
.
getDate
(),
now
.
getHours
());
}
const
oldTimestamps
=
[];
for
(
let
i
=
keepCount
;
i
<
keepCount
+
7
;
i
++
)
{
const
oldDate
=
new
Date
(
now
);
// 获取东八区当天凌晨3点时间
function
getTodayThreeAMTimestamp
():
Date
{
const
now
=
new
Date
();
const
today3AM
=
new
Date
(
now
.
getFullYear
(),
now
.
getMonth
(),
now
.
getDate
(),
3
,
0
,
0
);
if
(
interval
===
"
hour
"
)
{
oldDate
.
setHours
(
now
.
getHours
()
-
i
);
}
else
if
(
interval
===
"
day
"
)
{
oldDate
.
setDate
(
now
.
getDate
()
-
i
);
// 如果当前时间小于凌晨3点,返回前一天的凌晨3点
if
(
now
.
getHours
()
<
3
)
{
today3AM
.
setDate
(
today3AM
.
getDate
()
-
1
);
}
oldTimestamps
.
push
(
oldDate
.
toISOString
().
split
(
"
:
"
)[
0
]);
// 精确到小时,避免分钟秒
return
today3AM
;
}
// 计算截止时间(7个周期之前的时间戳)
function
getCutoffTimestamp
(
type
:
"
app-category
"
|
"
user-rank
"
):
number
{
if
(
type
===
"
app-category
"
)
{
const
currentHour
=
getCurrentHourTimestamp
();
const
cutoff
=
new
Date
(
currentHour
);
cutoff
.
setHours
(
cutoff
.
getHours
()
-
7
);
return
cutoff
.
getTime
();
}
else
{
const
today3AM
=
getTodayThreeAMTimestamp
();
const
cutoff
=
new
Date
(
today3AM
);
cutoff
.
setDate
(
cutoff
.
getDate
()
-
7
);
return
cutoff
.
getTime
();
}
}
// 获取需要删除的目录
async
function
getDirectoriesToDelete
(
supabase
,
bucket
:
string
,
type
:
"
app-category
"
|
"
user-rank
"
):
Promise
<
string
[]
>
{
try
{
const
{
data
,
error
}
=
await
supabase
.
storage
.
from
(
bucket
).
list
(
`
${
type
}
/`
,
{
limit
:
1000
,
});
if
(
error
)
{
console
.
error
(
`Failed to list directories in
${
type
}
:`
,
error
.
message
);
return
[];
}
const
cutoffTimestamp
=
getCutoffTimestamp
(
type
);
return
oldTimestamps
;
const
dirsToDelete
=
data
.
filter
(
item
=>
!
item
.
name
.
includes
(
'
.
'
))
// 只处理目录
.
filter
(
item
=>
{
const
dirTimestamp
=
parseInt
(
item
.
name
);
// 转为秒
if
(
isNaN
(
dirTimestamp
))
{
console
.
log
(
`Invalid timestamp directory:
${
item
.
name
}
`
);
return
false
;
}
const
dirDate
=
new
Date
(
dirTimestamp
*
1000
);
// 转为日期
const
shouldDelete
=
dirTimestamp
*
1000
<
cutoffTimestamp
;
// 确保单位统一为毫秒
console
.
log
(
`Directory "
${
item
.
name
}
" date:
${
dirDate
.
toISOString
()}
, should delete:
${
shouldDelete
}
`
);
return
shouldDelete
;
})
.
map
(
item
=>
item
.
name
);
console
.
log
(
`Found
${
dirsToDelete
.
length
}
directories to delete for
${
type
}
`
);
return
dirsToDelete
;
}
catch
(
err
)
{
console
.
error
(
`Error listing directories in
${
type
}
:`
,
err
);
return
[];
}
}
// 主逻辑处理
Deno
.
serve
(
async
(
req
)
=>
{
if
(
req
.
method
===
'
OPTIONS
'
)
{
return
new
Response
(
'
ok
'
,
{
headers
:
corsHeaders
})
if
(
req
.
method
===
"
OPTIONS
"
)
{
return
new
Response
(
"
ok
"
,
{
headers
:
corsHeaders
});
}
try
{
// const { name } = await req.json()
const
supabase
=
createClient
(
Deno
.
env
.
get
(
'
SUPABASE_URL
'
)
??
''
,
Deno
.
env
.
get
(
'
SUPABASE_ANON_KEY
'
)
??
''
,
{
global
:
{
headers
:
{
Authorization
:
req
.
headers
.
get
(
'
Authorization
'
)
!
}
}
}
)
const
currentTimestamp
=
new
Date
().
toISOString
();
// 处理 app-category:按小时保留前 7 个周期
const
oldAppCategoryDirs
=
getOldDirectories
(
currentTimestamp
,
"
hour
"
,
7
);
for
(
const
dir
of
oldAppCategoryDirs
)
{
await
deleteDirectory
(
"
cache
"
,
`app-category/
${
dir
}
`
);
const
supabaseUrl
=
Deno
.
env
.
get
(
"
SUPABASE_URL
"
);
const
supabaseAnonKey
=
Deno
.
env
.
get
(
"
SUPABASE_ANON_KEY
"
);
const
authHeader
=
req
.
headers
.
get
(
"
Authorization
"
);
if
(
!
supabaseUrl
||
!
supabaseAnonKey
||
!
authHeader
)
{
throw
new
Error
(
"
Missing Supabase configuration or Authorization header.
"
);
}
// 处理 user-rank:按天保留前 7 个周期
const
oldUserRankDirs
=
getOldDirectories
(
currentTimestamp
,
"
day
"
,
7
);
for
(
const
dir
of
oldUserRankDirs
)
{
await
deleteDirectory
(
"
cache
"
,
`user-rank/
${
dir
}
`
);
const
supabase
=
createClient
(
supabaseUrl
,
supabaseAnonKey
,
{
global
:
{
headers
:
{
Authorization
:
authHeader
}
},
});
console
.
log
(
"
Starting cleanup process...
"
);
// 处理 app-category(每小时)
const
appCategoryDirsToDelete
=
await
getDirectoriesToDelete
(
supabase
,
"
cache
"
,
"
app-category
"
);
for
(
const
dir
of
appCategoryDirsToDelete
)
{
await
deleteDirectory
(
supabase
,
"
cache
"
,
`app-category/
${
dir
}
`
);
}
return
new
Response
(
JSON
.
stringify
({
// 处理 user-rank(每天凌晨3点)
const
userRankDirsToDelete
=
await
getDirectoriesToDelete
(
supabase
,
"
cache
"
,
"
user-rank
"
);
for
(
const
dir
of
userRankDirsToDelete
)
{
await
deleteDirectory
(
supabase
,
"
cache
"
,
`user-rank/
${
dir
}
`
);
}
return
new
Response
(
JSON
.
stringify
({
code
:
200
,
data
:
null
,
message
:
'
success
'
}),
{
headers
:
{
'
Content-Type
'
:
'
application/json
'
},
status
:
200
,
})
data
:
{
appCategory
:
{
deletedDirs
:
appCategoryDirsToDelete
,
cutoffTime
:
new
Date
(
getCutoffTimestamp
(
"
app-category
"
)).
toISOString
(),
},
userRank
:
{
deletedDirs
:
userRankDirsToDelete
,
cutoffTime
:
new
Date
(
getCutoffTimestamp
(
"
user-rank
"
)).
toISOString
(),
},
},
message
:
"
success
"
,
}),
{
headers
:
{
...
corsHeaders
,
"
Content-Type
"
:
"
application/json
"
},
status
:
200
}
);
}
catch
(
err
)
{
return
new
Response
(
String
(
err
?.
message
??
err
),
{
status
:
500
})
console
.
error
(
"
Error in cleanup process:
"
,
err
);
return
new
Response
(
JSON
.
stringify
({
code
:
500
,
message
:
err
.
message
,
data
:
null
}),
{
headers
:
{
...
corsHeaders
,
"
Content-Type
"
:
"
application/json
"
},
status
:
500
}
);
}
})
})
;
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment