perf: remove edge function for faster fts (#19500)

Unlike embeddings, FTS doesn't require a server-side secret, so the Edge
Function is just adding an intermediate hop for no benefit.
This commit is contained in:
Charis
2023-12-07 12:05:29 -05:00
committed by GitHub
parent 4a35bc8c03
commit d429fba73f
3 changed files with 42 additions and 131 deletions
@@ -248,35 +248,51 @@ const DocsSearch = () => {
let sourcesLoaded = 0
const sources = ['search-fts', 'search-embeddings']
sources.forEach((source) => {
fetch(`${process.env.NEXT_PUBLIC_SUPABASE_URL}${FUNCTIONS_URL}${source}`, {
method: 'POST',
body: JSON.stringify({ query }),
})
.then((response) => response.json())
.then((results) => {
if (!Array.isArray(results)) {
throw Error("didn't get expected results array")
}
sourcesLoaded += 1
dispatch({
type: 'resultsReturned',
key: localKey,
sourcesLoaded,
results,
})
supabaseClient.rpc('docs_search_fts', { query: query.trim() }).then(({ data, error }) => {
sourcesLoaded += 1
if (error || !Array.isArray(data)) {
dispatch({
type: 'errored',
key: localKey,
sourcesLoaded,
message: error?.message ?? '',
})
.catch((error) => {
sourcesLoaded += 1
dispatch({
type: 'errored',
key: localKey,
sourcesLoaded,
message: error.message ?? '',
})
} else {
dispatch({
type: 'resultsReturned',
key: localKey,
sourcesLoaded,
results: data,
})
}
})
fetch(`${process.env.NEXT_PUBLIC_SUPABASE_URL}${FUNCTIONS_URL}search-embeddings`, {
method: 'POST',
body: JSON.stringify({ query }),
})
.then((response) => response.json())
.then((results) => {
if (!Array.isArray(results)) {
throw Error("didn't get expected results array")
}
sourcesLoaded += 1
dispatch({
type: 'resultsReturned',
key: localKey,
sourcesLoaded,
results,
})
})
.catch((error) => {
sourcesLoaded += 1
dispatch({
type: 'errored',
key: localKey,
sourcesLoaded,
message: error.message ?? '',
})
})
},
[supabaseClient]
)
-3
View File
@@ -71,8 +71,5 @@ redirect_uri = ""
# or any other third-party OIDC providers.
url = ""
[functions.search-fts]
verify_jwt = false
[functions.search-embeddings]
verify_jwt = false
-102
View File
@@ -1,102 +0,0 @@
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.8.0'
import { Database } from '../common/database-types.ts'
import { ApplicationError, UserError } from '../common/errors.ts'
const isDev = Deno.env.get('DENO_ENV') === 'development'
const supabaseUrl = Deno.env.get('SUPABASE_URL')
const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')
function getCorsHeaders(req) {
const receivedOrigin = req.headers.get('Origin')
const resolvedOrigin = /^https:\/\/[^.\/]+-supabase.vercel.app$/.test(receivedOrigin)
? receivedOrigin // Allow preview sites on Vercel to access function
: 'https://supabase.com'
return {
'Access-Control-Allow-Origin': isDev ? '*' : resolvedOrigin,
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
}
}
Deno.serve(async (req) => {
try {
// Handle CORS
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: getCorsHeaders(req) })
}
if (!supabaseUrl) {
throw new ApplicationError('Missing environment variable SUPABASE_URL')
}
if (!supabaseServiceKey) {
throw new ApplicationError('Missing environment variable SUPABASE_SERVICE_ROLE_KEY')
}
const requestData = await req.json()
if (!requestData) {
throw new UserError('Missing request data')
}
const { query } = requestData
if (!query) {
throw new UserError('Missing query in request data')
}
// Intentionally log the query
console.log({ query })
const sanitizedQuery = query.trim()
const supabaseClient = createClient<Database>(supabaseUrl, supabaseServiceKey)
const { data: searchData, error: searchError } = await supabaseClient.rpc('docs_search_fts', {
query: sanitizedQuery,
})
if (searchError) {
throw new ApplicationError('Failed to find search results', searchError)
}
return new Response(JSON.stringify(searchData), {
headers: {
...getCorsHeaders(req),
'Content-Type': 'application/json',
},
})
} catch (err) {
console.error(err)
if (err instanceof UserError) {
return new Response(
JSON.stringify({
error: err.message,
data: err.data,
}),
{
status: 400,
headers: { ...getCorsHeaders(req), 'Content-Type': 'application/json' },
}
)
} else if (err instanceof ApplicationError) {
// Print out application errors with their additional data
console.error(`${err.message}: ${JSON.stringify(err.data)}`)
} else {
// Print out unexpected errors as is to help with debugging
console.error(err)
}
// TODO: include more response info in debug environments
return new Response(
JSON.stringify({
error: 'There was an error processing your request',
}),
{
status: 500,
headers: { ...getCorsHeaders(req), 'Content-Type': 'application/json' },
}
)
}
})