⚡ Add cache into metadata fetching
This commit is contained in:
		
							
								
								
									
										48
									
								
								.idea/workspace.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										48
									
								
								.idea/workspace.xml
									
									
									
										generated
									
									
									
								
							@@ -4,9 +4,11 @@
 | 
				
			|||||||
    <option name="autoReloadType" value="ALL" />
 | 
					    <option name="autoReloadType" value="ALL" />
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
  <component name="ChangeListManager">
 | 
					  <component name="ChangeListManager">
 | 
				
			||||||
    <list default="true" id="18dd0d68-b4b8-40db-9734-9119b5c848bd" name="更改" comment=":arrow_up: Upgrade Passport to fix bug">
 | 
					    <list default="true" id="18dd0d68-b4b8-40db-9734-9119b5c848bd" name="更改" comment=":ambulance: Fix getting user panic">
 | 
				
			||||||
      <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
 | 
					      <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
 | 
				
			||||||
      <change beforePath="$PROJECT_DIR$/pkg/internal/server/api/attachments_api.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/internal/server/api/attachments_api.go" afterDir="false" />
 | 
					      <change beforePath="$PROJECT_DIR$/pkg/internal/server/api/attachments_api.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/internal/server/api/attachments_api.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/pkg/internal/services/attachments.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/internal/services/attachments.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/settings.toml" beforeDir="false" afterPath="$PROJECT_DIR$/settings.toml" afterDir="false" />
 | 
				
			||||||
    </list>
 | 
					    </list>
 | 
				
			||||||
    <option name="SHOW_DIALOG" value="false" />
 | 
					    <option name="SHOW_DIALOG" value="false" />
 | 
				
			||||||
    <option name="HIGHLIGHT_CONFLICTS" value="true" />
 | 
					    <option name="HIGHLIGHT_CONFLICTS" value="true" />
 | 
				
			||||||
@@ -36,27 +38,28 @@
 | 
				
			|||||||
    <option name="hideEmptyMiddlePackages" value="true" />
 | 
					    <option name="hideEmptyMiddlePackages" value="true" />
 | 
				
			||||||
    <option name="showLibraryContents" value="true" />
 | 
					    <option name="showLibraryContents" value="true" />
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
  <component name="PropertiesComponent">{
 | 
					  <component name="PropertiesComponent"><![CDATA[{
 | 
				
			||||||
  "keyToString": {
 | 
					  "keyToString": {
 | 
				
			||||||
    "DefaultGoTemplateProperty": "Go File",
 | 
					    "DefaultGoTemplateProperty": "Go File",
 | 
				
			||||||
    "Go Build.Backend.executor": "Run",
 | 
					    "Go Build.Backend.executor": "Run",
 | 
				
			||||||
    "Go 构建.Backend.executor": "Run",
 | 
					    "Go 构建.Backend.executor": "Run",
 | 
				
			||||||
    "RunOnceActivity.ShowReadmeOnStart": "true",
 | 
					    "RunOnceActivity.ShowReadmeOnStart": "true",
 | 
				
			||||||
    "RunOnceActivity.go.formatter.settings.were.checked": "true",
 | 
					    "RunOnceActivity.go.formatter.settings.were.checked": "true",
 | 
				
			||||||
    "RunOnceActivity.go.migrated.go.modules.settings": "true",
 | 
					    "RunOnceActivity.go.migrated.go.modules.settings": "true",
 | 
				
			||||||
    "RunOnceActivity.go.modules.automatic.dependencies.download": "true",
 | 
					    "RunOnceActivity.go.modules.automatic.dependencies.download": "true",
 | 
				
			||||||
    "RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true",
 | 
					    "RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true",
 | 
				
			||||||
    "git-widget-placeholder": "master",
 | 
					    "git-widget-placeholder": "master",
 | 
				
			||||||
    "go.import.settings.migrated": "true",
 | 
					    "go.import.settings.migrated": "true",
 | 
				
			||||||
    "go.sdk.automatically.set": "true",
 | 
					    "go.sdk.automatically.set": "true",
 | 
				
			||||||
    "last_opened_file_path": "/Users/littlesheep/Documents/Projects/Hydrogen/Paperclip/pkg/internal/grpc",
 | 
					    "last_opened_file_path": "/Users/littlesheep/Documents/Projects/Hydrogen/Paperclip/pkg/internal/grpc",
 | 
				
			||||||
    "node.js.detected.package.eslint": "true",
 | 
					    "node.js.detected.package.eslint": "true",
 | 
				
			||||||
    "node.js.selected.package.eslint": "(autodetect)",
 | 
					    "node.js.selected.package.eslint": "(autodetect)",
 | 
				
			||||||
    "nodejs_package_manager_path": "npm",
 | 
					    "nodejs_package_manager_path": "npm",
 | 
				
			||||||
    "run.code.analysis.last.selected.profile": "pProject Default",
 | 
					    "run.code.analysis.last.selected.profile": "pProject Default",
 | 
				
			||||||
    "settings.editor.selected.configurable": "preferences.lookFeel"
 | 
					    "settings.editor.selected.configurable": "preferences.lookFeel",
 | 
				
			||||||
 | 
					    "vue.rearranger.settings.migration": "true"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}</component>
 | 
					}]]></component>
 | 
				
			||||||
  <component name="RecentsManager">
 | 
					  <component name="RecentsManager">
 | 
				
			||||||
    <key name="CopyFile.RECENT_KEYS">
 | 
					    <key name="CopyFile.RECENT_KEYS">
 | 
				
			||||||
      <recent name="$PROJECT_DIR$/pkg/internal/grpc" />
 | 
					      <recent name="$PROJECT_DIR$/pkg/internal/grpc" />
 | 
				
			||||||
@@ -113,7 +116,8 @@
 | 
				
			|||||||
    <MESSAGE value="
:sparkles: Add health check" />
 | 
					    <MESSAGE value="
:sparkles: Add health check" />
 | 
				
			||||||
    <MESSAGE value=":arrow_up: Upgrade Passport and use Hyper SDK" />
 | 
					    <MESSAGE value=":arrow_up: Upgrade Passport and use Hyper SDK" />
 | 
				
			||||||
    <MESSAGE value=":arrow_up: Upgrade Passport to fix bug" />
 | 
					    <MESSAGE value=":arrow_up: Upgrade Passport to fix bug" />
 | 
				
			||||||
    <option name="LAST_COMMIT_MESSAGE" value=":arrow_up: Upgrade Passport to fix bug" />
 | 
					    <MESSAGE value=":ambulance: Fix getting user panic" />
 | 
				
			||||||
 | 
					    <option name="LAST_COMMIT_MESSAGE" value=":ambulance: Fix getting user panic" />
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
  <component name="VgoProject">
 | 
					  <component name="VgoProject">
 | 
				
			||||||
    <settings-migrated>true</settings-migrated>
 | 
					    <settings-migrated>true</settings-migrated>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -159,11 +159,11 @@ func updateAttachmentMeta(c *fiber.Ctx) error {
 | 
				
			|||||||
	attachment.Metadata = data.Metadata
 | 
						attachment.Metadata = data.Metadata
 | 
				
			||||||
	attachment.IsMature = data.IsMature
 | 
						attachment.IsMature = data.IsMature
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := database.C.Save(&attachment).Error; err != nil {
 | 
						if attachment, err := services.UpdateAttachment(attachment); err != nil {
 | 
				
			||||||
		return fiber.NewError(fiber.StatusBadRequest, err.Error())
 | 
							return fiber.NewError(fiber.StatusBadRequest, err.Error())
 | 
				
			||||||
	}
 | 
						} else {
 | 
				
			||||||
 | 
					 | 
				
			||||||
		return c.JSON(attachment)
 | 
							return c.JSON(attachment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func deleteAttachment(c *fiber.Ctx) error {
 | 
					func deleteAttachment(c *fiber.Ctx) error {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,23 +13,27 @@ import (
 | 
				
			|||||||
	"gorm.io/gorm"
 | 
						"gorm.io/gorm"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const metadataCacheLimit = 512
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var metadataCache = make(map[uint]models.Attachment)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetAttachmentByID(id uint) (models.Attachment, error) {
 | 
					func GetAttachmentByID(id uint) (models.Attachment, error) {
 | 
				
			||||||
 | 
						if val, ok := metadataCache[id]; ok {
 | 
				
			||||||
 | 
							return val, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var attachment models.Attachment
 | 
						var attachment models.Attachment
 | 
				
			||||||
	if err := database.C.Where(models.Attachment{
 | 
						if err := database.C.Where(models.Attachment{
 | 
				
			||||||
		BaseModel: models.BaseModel{ID: id},
 | 
							BaseModel: models.BaseModel{ID: id},
 | 
				
			||||||
	}).First(&attachment).Error; err != nil {
 | 
						}).First(&attachment).Error; err != nil {
 | 
				
			||||||
		return attachment, err
 | 
							return attachment, err
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if len(metadataCache) > metadataCacheLimit {
 | 
				
			||||||
 | 
								clear(metadataCache)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							metadataCache[id] = attachment
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return attachment, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetAttachmentByUUID(id string) (models.Attachment, error) {
 | 
					 | 
				
			||||||
	var attachment models.Attachment
 | 
					 | 
				
			||||||
	if err := database.C.Where(models.Attachment{
 | 
					 | 
				
			||||||
		Uuid: id,
 | 
					 | 
				
			||||||
	}).First(&attachment).Error; err != nil {
 | 
					 | 
				
			||||||
		return attachment, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return attachment, nil
 | 
						return attachment, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -61,7 +65,7 @@ func NewAttachmentMetadata(tx *gorm.DB, user models.Account, file *multipart.Fil
 | 
				
			|||||||
		attachment.Name = file.Filename
 | 
							attachment.Name = file.Filename
 | 
				
			||||||
		attachment.AccountID = user.ID
 | 
							attachment.AccountID = user.ID
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// If user didn't provide file mimetype manually, we gotta to detect it
 | 
							// If the user didn't provide file mimetype manually, we have to detect it
 | 
				
			||||||
		if len(attachment.MimeType) == 0 {
 | 
							if len(attachment.MimeType) == 0 {
 | 
				
			||||||
			if ext := filepath.Ext(attachment.Name); len(ext) > 0 {
 | 
								if ext := filepath.Ext(attachment.Name); len(ext) > 0 {
 | 
				
			||||||
				// Detect mimetype by file extensions
 | 
									// Detect mimetype by file extensions
 | 
				
			||||||
@@ -87,11 +91,29 @@ func NewAttachmentMetadata(tx *gorm.DB, user models.Account, file *multipart.Fil
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if err := tx.Save(&attachment).Error; err != nil {
 | 
						if err := tx.Save(&attachment).Error; err != nil {
 | 
				
			||||||
		return attachment, linked, fmt.Errorf("failed to save attachment record: %v", err)
 | 
							return attachment, linked, fmt.Errorf("failed to save attachment record: %v", err)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if len(metadataCache) > metadataCacheLimit {
 | 
				
			||||||
 | 
								clear(metadataCache)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							metadataCache[attachment.ID] = attachment
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return attachment, linked, nil
 | 
						return attachment, linked, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func UpdateAttachment(item models.Attachment) (models.Attachment, error) {
 | 
				
			||||||
 | 
						if err := database.C.Save(&item).Error; err != nil {
 | 
				
			||||||
 | 
							return item, err
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if len(metadataCache) > metadataCacheLimit {
 | 
				
			||||||
 | 
								clear(metadataCache)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							metadataCache[item.ID] = item
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return item, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func DeleteAttachment(item models.Attachment) error {
 | 
					func DeleteAttachment(item models.Attachment) error {
 | 
				
			||||||
	var dupeCount int64
 | 
						var dupeCount int64
 | 
				
			||||||
	if err := database.C.
 | 
						if err := database.C.
 | 
				
			||||||
@@ -103,6 +125,8 @@ func DeleteAttachment(item models.Attachment) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if err := database.C.Delete(&item).Error; err != nil {
 | 
						if err := database.C.Delete(&item).Error; err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							delete(metadataCache, item.ID)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if dupeCount != -1 && dupeCount <= 1 {
 | 
						if dupeCount != -1 && dupeCount <= 1 {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,7 +27,7 @@ prefix = "paperclip_"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[destinations.local]
 | 
					[destinations.local]
 | 
				
			||||||
type = "local"
 | 
					type = "local"
 | 
				
			||||||
path = "/uploads"
 | 
					path = "uploads"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[destinations.s3]
 | 
					[destinations.s3]
 | 
				
			||||||
type = "s3"
 | 
					type = "s3"
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user